[Pkg-swan-devel] [strongswan] 01/05: Imported Upstream version 5.2.0

Yves-Alexis Perez corsac at moszumanska.debian.org
Fri Jul 11 19:52:30 UTC 2014


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

corsac pushed a commit to branch master
in repository strongswan.

commit 81c63b0eed39432878f78727f60a1e7499645199
Author: Yves-Alexis Perez <corsac at debian.org>
Date:   Fri Jul 11 07:23:31 2014 +0200

    Imported Upstream version 5.2.0
---
 Android.common.mk                                  |    2 +-
 Android.mk                                         |    1 +
 Doxyfile.in                                        | 2346 ++++++++++-------
 Makefile.am                                        |    2 +-
 Makefile.in                                        |   21 +-
 NEWS                                               |   48 +
 README                                             | 1266 ++++-----
 aclocal.m4                                         |  139 +-
 conf/Makefile.am                                   |   10 +-
 conf/Makefile.in                                   |   38 +-
 conf/format-options.py                             |   51 +-
 conf/options/aikgen.conf                           |    7 +
 conf/options/aikgen.opt                            |    2 +
 conf/options/charon.conf                           |   20 +
 conf/options/charon.opt                            |   27 +
 conf/options/pki.conf                              |    7 +
 conf/options/pki.opt                               |    2 +
 conf/options/scepclient.conf                       |    7 +
 conf/options/scepclient.opt                        |    2 +
 conf/options/swanctl.conf                          |    7 +
 conf/options/swanctl.opt                           |    2 +
 conf/options/tools.conf                            |   14 -
 conf/options/tools.opt                             |    5 -
 conf/plugins/eap-tnc.conf                          |    2 +-
 conf/plugins/eap-tnc.opt                           |    2 +-
 conf/plugins/eap-ttls.conf                         |    3 +
 conf/plugins/eap-ttls.opt                          |    3 +
 conf/plugins/imc-attestation.conf                  |   21 -
 conf/plugins/imc-attestation.opt                   |   14 +-
 conf/plugins/imc-os.conf                           |    3 -
 conf/plugins/imc-os.opt                            |   14 +-
 conf/plugins/imc-scanner.conf                      |    3 -
 conf/plugins/imc-scanner.opt                       |    2 +-
 conf/plugins/imc-swid.conf                         |    3 -
 conf/plugins/imc-swid.opt                          |   11 +-
 conf/plugins/imc-test.conf                         |   15 -
 conf/plugins/imc-test.opt                          |   10 +-
 conf/plugins/imv-attestation.conf                  |   37 -
 conf/plugins/imv-attestation.opt                   |   22 +-
 conf/plugins/imv-os.conf                           |    3 -
 conf/plugins/imv-os.opt                            |    2 +-
 conf/plugins/imv-scanner.conf                      |    3 -
 conf/plugins/imv-scanner.opt                       |    2 +-
 conf/plugins/imv-swid.conf                         |    8 +
 conf/plugins/imv-swid.opt                          |    5 +
 conf/plugins/imv-test.conf                         |    3 -
 conf/plugins/imv-test.opt                          |    2 +-
 conf/plugins/kernel-klips.conf                     |   14 -
 conf/plugins/kernel-klips.opt                      |    5 -
 conf/plugins/load-tester.conf                      |    4 +
 conf/plugins/load-tester.opt                       |    4 +
 conf/plugins/vici.conf                             |   11 +
 conf/plugins/vici.opt                              |    2 +
 conf/strongswan.conf.5.main                        |  332 ++-
 config.h.in                                        |   16 +-
 configure                                          | 1221 ++++++---
 configure.ac                                       |  221 +-
 init/Makefile.in                                   |    6 +-
 init/systemd/Makefile.in                           |    6 +-
 man/Makefile.in                                    |    6 +-
 man/ipsec.conf.5.in                                |    9 +
 scripts/Makefile.am                                |    3 +-
 scripts/Makefile.in                                |   26 +-
 scripts/hash_burn.c                                |    3 +-
 scripts/settings-test.c                            |  126 +
 src/Makefile.am                                    |   20 +-
 src/Makefile.in                                    |   44 +-
 src/_copyright/Makefile.in                         |    6 +-
 src/_updown/Makefile.in                            |    6 +-
 src/_updown_espmark/Makefile.in                    |    6 +-
 src/aikgen/Makefile.am                             |   15 +
 src/aikgen/Makefile.in                             |  731 ++++++
 src/aikgen/aikgen.c                                |  554 ++++
 src/charon-cmd/Makefile.in                         |    6 +-
 src/charon-cmd/charon-cmd.c                        |    5 +-
 src/charon-cmd/cmd/cmd_connection.c                |    8 +-
 src/charon-cmd/cmd/cmd_creds.c                     |    4 +-
 src/charon-nm/Makefile.in                          |    6 +-
 src/charon-nm/nm/nm_service.c                      |    2 +
 src/charon-svc/Makefile.am                         |   16 +
 src/charon-svc/Makefile.in                         |  735 ++++++
 src/charon-svc/charon-svc.c                        |  333 +++
 src/charon-tkm/Makefile.in                         |    6 +-
 src/charon-tkm/src/tkm/tkm_kernel_ipsec.c          |    5 +-
 src/charon-tkm/src/tkm/tkm_listener.c              |    2 +-
 src/charon/Makefile.in                             |    6 +-
 src/charon/charon.c                                |   15 +-
 src/checksum/Makefile.am                           |   11 +-
 src/checksum/Makefile.in                           |   20 +-
 src/conftest/Makefile.am                           |    2 +-
 src/conftest/Makefile.in                           |    8 +-
 src/conftest/README                                |    2 +-
 src/conftest/config.c                              |    3 +
 src/conftest/hooks/add_notify.c                    |    5 +-
 src/conftest/hooks/add_payload.c                   |    3 +-
 src/conftest/hooks/custom_proposal.c               |    5 +-
 src/conftest/hooks/force_cookie.c                  |    2 +-
 src/conftest/hooks/ike_auth_fill.c                 |    2 +-
 src/conftest/hooks/log_id.c                        |    4 +-
 src/conftest/hooks/log_ke.c                        |    2 +-
 src/conftest/hooks/log_proposals.c                 |    2 +-
 src/conftest/hooks/log_ts.c                        |    4 +-
 src/conftest/hooks/pretend_auth.c                  |   18 +-
 src/conftest/hooks/rebuild_auth.c                  |    6 +-
 src/conftest/hooks/set_critical.c                  |    3 +-
 src/conftest/hooks/set_length.c                    |    3 +-
 src/conftest/hooks/set_proposal_number.c           |    2 +-
 src/conftest/hooks/set_reserved.c                  |   13 +-
 src/conftest/hooks/unencrypted_notify.c            |    5 +-
 src/conftest/hooks/unsort_message.c                |    3 +-
 src/dumm/Makefile.in                               |    6 +-
 src/dumm/ext/dumm.c                                |    2 +
 src/include/Makefile.in                            |    6 +-
 src/ipsec/Makefile.in                              |    6 +-
 src/ipsec/_ipsec.8                                 |    2 +-
 src/ipsec/_ipsec.in                                |    6 +-
 src/libcharon/Android.mk                           |    5 +-
 src/libcharon/Makefile.am                          |   37 +-
 src/libcharon/Makefile.in                          |  463 ++--
 src/libcharon/bus/bus.c                            |   92 +-
 src/libcharon/bus/bus.h                            |    8 +
 src/libcharon/bus/listeners/file_logger.c          |   14 +
 src/libcharon/bus/listeners/listener.h             |   18 +-
 src/libcharon/config/child_cfg.c                   |   31 +-
 src/libcharon/config/child_cfg.h                   |   20 +-
 src/libcharon/config/ike_cfg.c                     |    5 +-
 src/libcharon/config/ike_cfg.h                     |    5 +-
 src/libcharon/config/peer_cfg.c                    |    3 +-
 src/libcharon/config/proposal.c                    |  170 +-
 src/libcharon/config/proposal.h                    |    8 +
 src/libcharon/control/controller.c                 |    1 -
 src/libcharon/daemon.c                             |   80 +-
 src/libcharon/encoding/generator.c                 |   19 +-
 src/libcharon/encoding/message.c                   |  753 +++---
 src/libcharon/encoding/parser.c                    |   19 +-
 src/libcharon/encoding/payloads/auth_payload.c     |    4 +-
 src/libcharon/encoding/payloads/cert_payload.c     |    4 +-
 src/libcharon/encoding/payloads/certreq_payload.c  |   12 +-
 .../encoding/payloads/configuration_attribute.c    |    8 +-
 .../encoding/payloads/configuration_attribute.h    |    6 +-
 src/libcharon/encoding/payloads/cp_payload.c       |   10 +-
 src/libcharon/encoding/payloads/cp_payload.h       |    4 +-
 src/libcharon/encoding/payloads/delete_payload.c   |   12 +-
 src/libcharon/encoding/payloads/delete_payload.h   |    2 +-
 src/libcharon/encoding/payloads/eap_payload.c      |    4 +-
 .../encoding/payloads/encryption_payload.c         |   16 +-
 .../encoding/payloads/encryption_payload.h         |    2 +-
 src/libcharon/encoding/payloads/endpoint_notify.c  |    2 +-
 src/libcharon/encoding/payloads/fragment_payload.c |    4 +-
 src/libcharon/encoding/payloads/hash_payload.c     |    4 +-
 src/libcharon/encoding/payloads/hash_payload.h     |    2 +-
 src/libcharon/encoding/payloads/id_payload.c       |   12 +-
 src/libcharon/encoding/payloads/id_payload.h       |    6 +-
 src/libcharon/encoding/payloads/ike_header.c       |    2 +-
 src/libcharon/encoding/payloads/ke_payload.c       |    8 +-
 src/libcharon/encoding/payloads/ke_payload.h       |    4 +-
 src/libcharon/encoding/payloads/nonce_payload.c    |    8 +-
 src/libcharon/encoding/payloads/nonce_payload.h    |    2 +-
 src/libcharon/encoding/payloads/notify_payload.c   |   12 +-
 src/libcharon/encoding/payloads/notify_payload.h   |    4 +-
 src/libcharon/encoding/payloads/payload.c          |  154 +-
 src/libcharon/encoding/payloads/payload.h          |  118 +-
 .../encoding/payloads/proposal_substructure.c      |   82 +-
 .../encoding/payloads/proposal_substructure.h      |   10 +-
 src/libcharon/encoding/payloads/sa_payload.c       |   20 +-
 src/libcharon/encoding/payloads/sa_payload.h       |    2 +-
 .../payloads/traffic_selector_substructure.c       |    4 +-
 .../encoding/payloads/transform_attribute.c        |    4 +-
 .../encoding/payloads/transform_attribute.h        |    4 +-
 .../encoding/payloads/transform_substructure.c     |   20 +-
 .../encoding/payloads/transform_substructure.h     |    4 +-
 src/libcharon/encoding/payloads/ts_payload.c       |    8 +-
 src/libcharon/encoding/payloads/unknown_payload.c  |    2 +-
 .../encoding/payloads/vendor_id_payload.c          |    2 +-
 .../encoding/payloads/vendor_id_payload.h          |    4 +-
 src/libcharon/network/receiver.c                   |    2 +-
 src/libcharon/plugins/addrblock/Makefile.am        |    2 +-
 src/libcharon/plugins/addrblock/Makefile.in        |    8 +-
 src/libcharon/plugins/android_dns/Makefile.am      |    2 +-
 src/libcharon/plugins/android_dns/Makefile.in      |    8 +-
 src/libcharon/plugins/android_log/Makefile.am      |    2 +-
 src/libcharon/plugins/android_log/Makefile.in      |    8 +-
 src/libcharon/plugins/certexpire/Makefile.am       |    2 +-
 src/libcharon/plugins/certexpire/Makefile.in       |    8 +-
 src/libcharon/plugins/coupling/Makefile.am         |    2 +-
 src/libcharon/plugins/coupling/Makefile.in         |    8 +-
 .../plugins/coupling/coupling_validator.c          |   10 +-
 src/libcharon/plugins/dhcp/Makefile.am             |    2 +-
 src/libcharon/plugins/dhcp/Makefile.in             |    8 +-
 src/libcharon/plugins/dnscert/Makefile.am          |    2 +-
 src/libcharon/plugins/dnscert/Makefile.in          |    8 +-
 src/libcharon/plugins/duplicheck/Makefile.am       |    2 +-
 src/libcharon/plugins/duplicheck/Makefile.in       |    8 +-
 src/libcharon/plugins/eap_aka/Makefile.am          |    2 +-
 src/libcharon/plugins/eap_aka/Makefile.in          |    8 +-
 src/libcharon/plugins/eap_aka_3gpp2/Makefile.am    |    2 +-
 src/libcharon/plugins/eap_aka_3gpp2/Makefile.in    |    8 +-
 src/libcharon/plugins/eap_dynamic/Makefile.am      |    2 +-
 src/libcharon/plugins/eap_dynamic/Makefile.in      |    8 +-
 src/libcharon/plugins/eap_gtc/Makefile.am          |    2 +-
 src/libcharon/plugins/eap_gtc/Makefile.in          |    8 +-
 src/libcharon/plugins/eap_gtc/eap_gtc.c            |    6 +-
 src/libcharon/plugins/eap_identity/Makefile.am     |    2 +-
 src/libcharon/plugins/eap_identity/Makefile.in     |    8 +-
 src/libcharon/plugins/eap_md5/Makefile.am          |    2 +-
 src/libcharon/plugins/eap_md5/Makefile.in          |    8 +-
 src/libcharon/plugins/eap_mschapv2/Makefile.am     |    2 +-
 src/libcharon/plugins/eap_mschapv2/Makefile.in     |    8 +-
 src/libcharon/plugins/eap_peap/Makefile.am         |    2 +-
 src/libcharon/plugins/eap_peap/Makefile.in         |    8 +-
 src/libcharon/plugins/eap_peap/eap_peap_avp.c      |   15 -
 src/libcharon/plugins/eap_radius/Makefile.am       |    2 +-
 src/libcharon/plugins/eap_radius/Makefile.in       |    8 +-
 .../plugins/eap_radius/eap_radius_accounting.c     |    2 +-
 .../plugins/eap_radius/eap_radius_forward.c        |    7 +-
 .../plugins/eap_radius/eap_radius_xauth.c          |   10 +-
 src/libcharon/plugins/eap_sim/Makefile.am          |    2 +-
 src/libcharon/plugins/eap_sim/Makefile.in          |    8 +-
 src/libcharon/plugins/eap_sim_file/Makefile.am     |    2 +-
 src/libcharon/plugins/eap_sim_file/Makefile.in     |    8 +-
 src/libcharon/plugins/eap_sim_pcsc/Makefile.am     |    2 +-
 src/libcharon/plugins/eap_sim_pcsc/Makefile.in     |    8 +-
 .../plugins/eap_simaka_pseudonym/Makefile.am       |    2 +-
 .../plugins/eap_simaka_pseudonym/Makefile.in       |    8 +-
 .../plugins/eap_simaka_reauth/Makefile.am          |    2 +-
 .../plugins/eap_simaka_reauth/Makefile.in          |    8 +-
 src/libcharon/plugins/eap_simaka_sql/Makefile.am   |    2 +-
 src/libcharon/plugins/eap_simaka_sql/Makefile.in   |    8 +-
 src/libcharon/plugins/eap_tls/Makefile.am          |    2 +-
 src/libcharon/plugins/eap_tls/Makefile.in          |    8 +-
 src/libcharon/plugins/eap_tnc/Makefile.am          |    2 +-
 src/libcharon/plugins/eap_tnc/Makefile.in          |    8 +-
 src/libcharon/plugins/eap_tnc/eap_tnc.c            |   54 +-
 src/libcharon/plugins/eap_tnc/eap_tnc.h            |   28 +-
 src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c     |    8 +
 src/libcharon/plugins/eap_ttls/Makefile.am         |    2 +-
 src/libcharon/plugins/eap_ttls/Makefile.in         |    8 +-
 src/libcharon/plugins/eap_ttls/eap_ttls_server.c   |   30 +-
 src/libcharon/plugins/error_notify/Makefile.am     |    2 +-
 src/libcharon/plugins/error_notify/Makefile.in     |    8 +-
 src/libcharon/plugins/farp/Makefile.am             |    2 +-
 src/libcharon/plugins/farp/Makefile.in             |    8 +-
 src/libcharon/plugins/ha/Makefile.am               |    2 +-
 src/libcharon/plugins/ha/Makefile.in               |    8 +-
 src/libcharon/plugins/ha/ha_dispatcher.c           |   10 +-
 src/libcharon/plugins/ha/ha_tunnel.c               |    2 +
 src/libcharon/plugins/ipseckey/Makefile.am         |    2 +-
 src/libcharon/plugins/ipseckey/Makefile.in         |    8 +-
 src/libcharon/plugins/kernel_iph/Makefile.am       |   20 +
 src/libcharon/plugins/kernel_iph/Makefile.in       |  768 ++++++
 src/libcharon/plugins/kernel_iph/kernel_iph_net.c  |  775 ++++++
 src/libcharon/plugins/kernel_iph/kernel_iph_net.h  |   46 +
 .../plugins/kernel_iph/kernel_iph_plugin.c         |   76 +
 .../plugins/kernel_iph/kernel_iph_plugin.h         |   42 +
 src/libcharon/plugins/kernel_libipsec/Makefile.am  |    2 +-
 src/libcharon/plugins/kernel_libipsec/Makefile.in  |    8 +-
 .../kernel_libipsec/kernel_libipsec_ipsec.c        |    9 +-
 src/libcharon/plugins/kernel_wfp/Makefile.am       |   33 +
 src/libcharon/plugins/kernel_wfp/Makefile.in       |  801 ++++++
 src/libcharon/plugins/kernel_wfp/ipsecdump.c       |  666 +++++
 .../plugins/kernel_wfp/kernel_wfp_compat.c         |  157 ++
 .../plugins/kernel_wfp/kernel_wfp_compat.h         |  205 ++
 .../plugins/kernel_wfp/kernel_wfp_ipsec.c          | 2551 ++++++++++++++++++
 .../plugins/kernel_wfp/kernel_wfp_ipsec.h          |   47 +
 .../plugins/kernel_wfp/kernel_wfp_plugin.c         |   77 +
 .../plugins/kernel_wfp/kernel_wfp_plugin.h         |   43 +
 .../plugins/kernel_wfp/mingw-w64-4.8.1.diff        |   26 +
 src/libcharon/plugins/led/Makefile.am              |    2 +-
 src/libcharon/plugins/led/Makefile.in              |    8 +-
 src/libcharon/plugins/load_tester/Makefile.am      |    2 +-
 src/libcharon/plugins/load_tester/Makefile.in      |    8 +-
 .../plugins/load_tester/load_tester_config.c       |    4 +-
 .../plugins/load_tester/load_tester_creds.c        |   26 +-
 .../plugins/load_tester/load_tester_ipsec.c        |    9 +-
 src/libcharon/plugins/lookip/Makefile.am           |    2 +-
 src/libcharon/plugins/lookip/Makefile.in           |    8 +-
 src/libcharon/plugins/maemo/Makefile.am            |    2 +-
 src/libcharon/plugins/maemo/Makefile.in            |    8 +-
 src/libcharon/plugins/maemo/maemo_service.c        |    2 +
 src/libcharon/plugins/medcli/Makefile.am           |    2 +-
 src/libcharon/plugins/medcli/Makefile.in           |    8 +-
 src/libcharon/plugins/medcli/medcli_config.c       |    4 +
 src/libcharon/plugins/medsrv/Makefile.am           |    2 +-
 src/libcharon/plugins/medsrv/Makefile.in           |    8 +-
 src/libcharon/plugins/medsrv/medsrv_config.c       |    1 +
 src/libcharon/plugins/osx_attr/Makefile.am         |    2 +-
 src/libcharon/plugins/osx_attr/Makefile.in         |    8 +-
 src/libcharon/plugins/radattr/Makefile.am          |    2 +-
 src/libcharon/plugins/radattr/Makefile.in          |    8 +-
 src/libcharon/plugins/radattr/radattr_listener.c   |    4 +-
 src/libcharon/plugins/smp/Makefile.am              |    2 +-
 src/libcharon/plugins/smp/Makefile.in              |    8 +-
 src/libcharon/plugins/socket_default/Makefile.am   |    2 +-
 src/libcharon/plugins/socket_default/Makefile.in   |    8 +-
 src/libcharon/plugins/socket_dynamic/Makefile.am   |    2 +-
 src/libcharon/plugins/socket_dynamic/Makefile.in   |    8 +-
 src/libcharon/plugins/socket_win/Makefile.am       |   21 +
 src/libcharon/plugins/socket_win/Makefile.in       |  769 ++++++
 .../plugins/socket_win/socket_win_plugin.c         |   76 +
 .../plugins/socket_win/socket_win_plugin.h         |   42 +
 .../plugins/socket_win/socket_win_socket.c         |  501 ++++
 .../plugins/socket_win/socket_win_socket.h         |   44 +
 src/libcharon/plugins/sql/Makefile.am              |    2 +-
 src/libcharon/plugins/sql/Makefile.in              |    8 +-
 src/libcharon/plugins/sql/sql_config.c             |    2 +
 src/libcharon/plugins/stroke/Makefile.am           |    2 +-
 src/libcharon/plugins/stroke/Makefile.in           |    8 +-
 src/libcharon/plugins/stroke/stroke_config.c       |    6 +
 src/libcharon/plugins/stroke/stroke_socket.c       |   90 +-
 src/libcharon/plugins/systime_fix/Makefile.in      |    6 +-
 src/libcharon/plugins/tnc_ifmap/Makefile.am        |    2 +-
 src/libcharon/plugins/tnc_ifmap/Makefile.in        |    8 +-
 src/libcharon/plugins/tnc_pdp/Makefile.am          |    2 +-
 src/libcharon/plugins/tnc_pdp/Makefile.in          |    8 +-
 src/libcharon/plugins/tnc_pdp/tnc_pdp.c            |   91 +-
 src/libcharon/plugins/uci/Makefile.am              |    2 +-
 src/libcharon/plugins/uci/Makefile.in              |    8 +-
 src/libcharon/plugins/unit_tester/Makefile.am      |    2 +-
 src/libcharon/plugins/unit_tester/Makefile.in      |    8 +-
 src/libcharon/plugins/unity/Makefile.am            |    2 +-
 src/libcharon/plugins/unity/Makefile.in            |    8 +-
 src/libcharon/plugins/updown/Makefile.am           |    2 +-
 src/libcharon/plugins/updown/Makefile.in           |    8 +-
 src/libcharon/plugins/updown/updown_listener.c     |    4 +-
 src/libcharon/plugins/vici/Makefile.am             |   69 +
 src/libcharon/plugins/vici/Makefile.in             | 1183 +++++++++
 src/libcharon/plugins/vici/README.md               |  176 ++
 src/libcharon/plugins/vici/libvici.c               |  764 ++++++
 src/libcharon/plugins/vici/libvici.h               |  459 ++++
 src/libcharon/plugins/vici/suites/test_event.c     |  224 ++
 src/libcharon/plugins/vici/suites/test_message.c   |  407 +++
 src/libcharon/plugins/vici/suites/test_request.c   |  247 ++
 src/libcharon/plugins/vici/suites/test_socket.c    |  133 +
 src/libcharon/plugins/vici/vici_attribute.c        |  713 +++++
 src/libcharon/plugins/vici/vici_attribute.h        |   54 +
 src/libcharon/plugins/vici/vici_builder.c          |  253 ++
 src/libcharon/plugins/vici/vici_builder.h          |  129 +
 src/libcharon/plugins/vici/vici_config.c           | 2006 ++++++++++++++
 src/libcharon/plugins/vici/vici_config.h           |   53 +
 src/libcharon/plugins/vici/vici_control.c          |  496 ++++
 src/libcharon/plugins/vici/vici_control.h          |   47 +
 src/libcharon/plugins/vici/vici_cred.c             |  330 +++
 src/libcharon/plugins/vici/vici_cred.h             |   47 +
 src/libcharon/plugins/vici/vici_dispatcher.c       |  524 ++++
 src/libcharon/plugins/vici/vici_dispatcher.h       |  122 +
 src/libcharon/plugins/vici/vici_logger.c           |  130 +
 src/libcharon/plugins/vici/vici_logger.h           |   54 +
 src/libcharon/plugins/vici/vici_message.c          |  727 ++++++
 src/libcharon/plugins/vici/vici_message.h          |  248 ++
 src/libcharon/plugins/vici/vici_plugin.c           |  169 ++
 src/libcharon/plugins/vici/vici_plugin.h           |   42 +
 src/libcharon/plugins/vici/vici_query.c            | 1039 ++++++++
 src/libcharon/plugins/vici/vici_query.h            |   47 +
 src/libcharon/plugins/vici/vici_socket.c           |  679 +++++
 src/libcharon/plugins/vici/vici_socket.h           |   95 +
 src/libcharon/plugins/vici/vici_tests.c            |   46 +
 src/libcharon/plugins/vici/vici_tests.h            |   19 +
 src/libcharon/plugins/whitelist/Makefile.am        |    2 +-
 src/libcharon/plugins/whitelist/Makefile.in        |    8 +-
 src/libcharon/plugins/xauth_eap/Makefile.am        |    2 +-
 src/libcharon/plugins/xauth_eap/Makefile.in        |    8 +-
 src/libcharon/plugins/xauth_eap/xauth_eap.c        |    6 +-
 src/libcharon/plugins/xauth_generic/Makefile.am    |    2 +-
 src/libcharon/plugins/xauth_generic/Makefile.in    |    8 +-
 .../plugins/xauth_generic/xauth_generic.c          |   12 +-
 src/libcharon/plugins/xauth_noauth/Makefile.am     |    2 +-
 src/libcharon/plugins/xauth_noauth/Makefile.in     |    8 +-
 src/libcharon/plugins/xauth_pam/Makefile.am        |    2 +-
 src/libcharon/plugins/xauth_pam/Makefile.in        |    8 +-
 src/libcharon/plugins/xauth_pam/xauth_pam.c        |   13 +-
 .../plugins/xauth_pam/xauth_pam_listener.h         |    2 +-
 .../processing/jobs/process_message_job.c          |    2 +-
 src/libcharon/processing/jobs/rekey_ike_sa_job.c   |   49 +-
 src/libcharon/sa/authenticator.c                   |    2 +-
 src/libcharon/sa/child_sa.c                        |   31 +-
 src/libcharon/sa/ike_sa.c                          |   51 +-
 src/libcharon/sa/ike_sa.h                          |   26 +-
 src/libcharon/sa/ike_sa_manager.c                  |   19 +-
 .../sa/ikev1/authenticators/psk_v1_authenticator.c |    4 +-
 .../ikev1/authenticators/pubkey_v1_authenticator.c |    4 +-
 src/libcharon/sa/ikev1/keymat_v1.c                 |    6 +-
 src/libcharon/sa/ikev1/phase1.c                    |   10 +-
 src/libcharon/sa/ikev1/task_manager_v1.c           |    8 +-
 src/libcharon/sa/ikev1/tasks/aggressive_mode.c     |   16 +-
 src/libcharon/sa/ikev1/tasks/informational.c       |    4 +-
 src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c    |    6 +-
 src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c     |    8 +-
 src/libcharon/sa/ikev1/tasks/isakmp_delete.c       |    2 +-
 src/libcharon/sa/ikev1/tasks/isakmp_dpd.c          |    2 +-
 src/libcharon/sa/ikev1/tasks/isakmp_natd.c         |   16 +-
 src/libcharon/sa/ikev1/tasks/isakmp_vendor.c       |    6 +-
 src/libcharon/sa/ikev1/tasks/main_mode.c           |   16 +-
 src/libcharon/sa/ikev1/tasks/mode_config.c         |   33 +-
 src/libcharon/sa/ikev1/tasks/quick_delete.c        |    4 +-
 src/libcharon/sa/ikev1/tasks/quick_mode.c          |   24 +-
 src/libcharon/sa/ikev1/tasks/xauth.c               |   20 +-
 .../sa/ikev2/authenticators/eap_authenticator.c    |    6 +-
 .../sa/ikev2/authenticators/psk_authenticator.c    |    2 +-
 .../sa/ikev2/authenticators/pubkey_authenticator.c |    2 +-
 src/libcharon/sa/ikev2/connect_manager.c           |    2 +-
 src/libcharon/sa/ikev2/task_manager_v2.c           |   10 +-
 src/libcharon/sa/ikev2/tasks/child_create.c        |   30 +-
 src/libcharon/sa/ikev2/tasks/child_delete.c        |    6 +-
 src/libcharon/sa/ikev2/tasks/child_rekey.c         |    6 +-
 src/libcharon/sa/ikev2/tasks/ike_auth.c            |   28 +-
 src/libcharon/sa/ikev2/tasks/ike_cert_post.c       |   14 +-
 src/libcharon/sa/ikev2/tasks/ike_cert_pre.c        |    8 +-
 src/libcharon/sa/ikev2/tasks/ike_config.c          |   25 +-
 src/libcharon/sa/ikev2/tasks/ike_delete.c          |    2 +-
 src/libcharon/sa/ikev2/tasks/ike_init.c            |   12 +-
 src/libcharon/sa/ikev2/tasks/ike_me.c              |   10 +-
 src/libcharon/sa/ikev2/tasks/ike_mobike.c          |    2 +-
 src/libcharon/sa/ikev2/tasks/ike_natd.c            |    6 +-
 src/libcharon/sa/ikev2/tasks/ike_rekey.c           |   14 +-
 src/libcharon/sa/ikev2/tasks/ike_vendor.c          |    4 +-
 src/libcharon/sa/shunt_manager.c                   |   43 +-
 src/libfast/Makefile.am                            |    2 +-
 src/libfast/Makefile.in                            |    8 +-
 src/libhydra/Makefile.am                           |   11 +-
 src/libhydra/Makefile.in                           |   63 +-
 src/libhydra/attributes/attributes.h               |    2 +-
 src/libhydra/kernel/kernel_interface.c             |   14 +-
 src/libhydra/kernel/kernel_interface.h             |    9 +-
 src/libhydra/kernel/kernel_ipsec.h                 |    2 +
 src/libhydra/kernel/kernel_net.h                   |    4 +-
 src/libhydra/plugins/attr/Makefile.am              |    2 +-
 src/libhydra/plugins/attr/Makefile.in              |    8 +-
 src/libhydra/plugins/attr_sql/Makefile.am          |    2 +-
 src/libhydra/plugins/attr_sql/Makefile.in          |    8 +-
 src/libhydra/plugins/kernel_klips/Makefile.am      |   18 -
 src/libhydra/plugins/kernel_klips/Makefile.in      |  762 ------
 .../plugins/kernel_klips/kernel_klips_ipsec.c      | 2652 -------------------
 .../plugins/kernel_klips/kernel_klips_ipsec.h      |   46 -
 .../plugins/kernel_klips/kernel_klips_plugin.c     |   76 -
 .../plugins/kernel_klips/kernel_klips_plugin.h     |   42 -
 src/libhydra/plugins/kernel_klips/pfkeyv2.h        |  322 ---
 src/libhydra/plugins/kernel_netlink/Makefile.am    |    2 +-
 src/libhydra/plugins/kernel_netlink/Makefile.in    |    8 +-
 .../plugins/kernel_netlink/kernel_netlink_ipsec.c  |   88 +-
 .../plugins/kernel_netlink/kernel_netlink_net.c    |  264 +-
 src/libhydra/plugins/kernel_pfkey/Makefile.am      |    2 +-
 src/libhydra/plugins/kernel_pfkey/Makefile.in      |    8 +-
 .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c      |  206 +-
 src/libhydra/plugins/kernel_pfroute/Makefile.am    |    2 +-
 src/libhydra/plugins/kernel_pfroute/Makefile.in    |    8 +-
 .../plugins/kernel_pfroute/kernel_pfroute_net.c    |    2 +-
 src/libhydra/plugins/resolve/Makefile.am           |    2 +-
 src/libhydra/plugins/resolve/Makefile.in           |    8 +-
 src/libimcv/Android.mk                             |   66 +
 src/libimcv/Makefile.am                            |   11 +-
 src/libimcv/Makefile.in                            |   52 +-
 src/libimcv/ietf/ietf_attr_installed_packages.c    |   10 +-
 src/libimcv/ietf/ietf_attr_installed_packages.h    |    3 +-
 src/libimcv/imc/imc_agent.c                        |    3 +-
 src/libimcv/imc/imc_msg.c                          |   18 +-
 src/libimcv/imc/imc_os_info.c                      |  632 +++++
 src/libimcv/imc/imc_os_info.h                      |  107 +
 src/libimcv/imcv.c                                 |   51 +-
 src/libimcv/imcv.h                                 |    6 +
 src/libimcv/imv/_imv_policy                        |   14 +-
 src/libimcv/imv/data.sql                           |  345 ++-
 src/libimcv/imv/imv_agent.c                        |   48 +-
 src/libimcv/imv/imv_agent.h                        |    4 +-
 src/libimcv/imv/imv_database.c                     |  302 +--
 src/libimcv/imv/imv_database.h                     |   20 -
 src/libimcv/imv/imv_if.h                           |   55 +-
 src/libimcv/imv/imv_os_info.c                      |  168 ++
 src/libimcv/imv/imv_os_info.h                      |   88 +
 src/libimcv/imv/imv_policy_manager.c               |   13 +-
 src/libimcv/imv/imv_policy_manager_usage.c         |    3 +-
 src/libimcv/imv/imv_session.c                      |  147 +-
 src/libimcv/imv/imv_session.h                      |   80 +-
 src/libimcv/imv/imv_session_manager.c              |  131 +
 src/libimcv/imv/imv_session_manager.h              |   69 +
 src/libimcv/imv/imv_state.h                        |   27 +-
 src/libimcv/imv/tables-mysql.sql                   |  200 ++
 src/libimcv/imv/tables.sql                         |  151 +-
 src/libimcv/os_info/os_info.c                      |  553 +---
 src/libimcv/os_info/os_info.h                      |   82 +-
 src/libimcv/pa_tnc/pa_tnc_attr.h                   |    6 +-
 src/libimcv/pa_tnc/pa_tnc_msg.c                    |   21 +-
 src/libimcv/pa_tnc/pa_tnc_msg.h                    |    3 +-
 src/libimcv/plugins/imc_os/Makefile.am             |    2 +-
 src/libimcv/plugins/imc_os/Makefile.in             |    8 +-
 src/libimcv/plugins/imc_os/imc_os.c                |  165 +-
 src/libimcv/plugins/imc_scanner/Makefile.am        |    2 +-
 src/libimcv/plugins/imc_scanner/Makefile.in        |    8 +-
 src/libimcv/plugins/imc_test/Makefile.am           |    2 +-
 src/libimcv/plugins/imc_test/Makefile.in           |    8 +-
 src/libimcv/plugins/imv_os/Makefile.am             |    4 +-
 src/libimcv/plugins/imv_os/Makefile.in             |   26 +-
 src/libimcv/plugins/imv_os/imv_os_agent.c          |  164 +-
 src/libimcv/plugins/imv_os/imv_os_database.c       |   67 +-
 src/libimcv/plugins/imv_os/imv_os_database.h       |   14 +-
 src/libimcv/plugins/imv_os/imv_os_state.c          |  136 +-
 src/libimcv/plugins/imv_os/imv_os_state.h          |   37 +-
 src/libimcv/plugins/imv_os/pacman.sh               |   23 +-
 src/libimcv/plugins/imv_scanner/Makefile.am        |    2 +-
 src/libimcv/plugins/imv_scanner/Makefile.in        |    8 +-
 .../plugins/imv_scanner/imv_scanner_agent.c        |    5 +-
 .../plugins/imv_scanner/imv_scanner_state.c        |   44 +-
 src/libimcv/plugins/imv_test/Makefile.am           |    2 +-
 src/libimcv/plugins/imv_test/Makefile.in           |    8 +-
 src/libimcv/plugins/imv_test/imv_test_state.c      |   36 +-
 src/libipsec/Makefile.in                           |    6 +-
 src/libipsec/esp_packet.c                          |    4 +-
 src/libipsec/ip_packet.c                           |    4 +-
 src/libipsec/ipsec_policy_mgr.c                    |    5 +-
 src/libpts/Android.mk                              |   78 +
 src/libpts/Makefile.am                             |    8 +
 src/libpts/Makefile.in                             |   39 +-
 src/libpts/plugins/imc_attestation/Makefile.am     |    2 +-
 src/libpts/plugins/imc_attestation/Makefile.in     |    8 +-
 .../plugins/imc_attestation/imc_attestation.c      |   54 +-
 src/libpts/plugins/imc_swid/Makefile.am            |    2 +-
 src/libpts/plugins/imc_swid/Makefile.in            |    8 +-
 src/libpts/plugins/imc_swid/imc_swid.c             |  208 +-
 ...id.2004-03.org.strongswan_strongSwan.swidtag.in |   40 +-
 src/libpts/plugins/imv_attestation/Makefile.am     |    2 +-
 src/libpts/plugins/imv_attestation/Makefile.in     |    8 +-
 src/libpts/plugins/imv_attestation/attest.c        |   57 +-
 src/libpts/plugins/imv_attestation/attest_db.c     |  207 +-
 src/libpts/plugins/imv_attestation/attest_db.h     |   10 +-
 .../plugins/imv_attestation/build-database.sh      |  293 +--
 .../imv_attestation/imv_attestation_agent.c        |  230 +-
 .../imv_attestation/imv_attestation_build.c        |   14 +-
 .../imv_attestation/imv_attestation_process.c      |   93 +-
 .../imv_attestation/imv_attestation_state.c        |   68 +-
 .../imv_attestation/imv_attestation_state.h        |   26 +-
 src/libpts/plugins/imv_swid/Makefile.am            |    8 +-
 src/libpts/plugins/imv_swid/Makefile.in            |   17 +-
 src/libpts/plugins/imv_swid/imv_swid_agent.c       |  359 ++-
 src/libpts/plugins/imv_swid/imv_swid_rest.c        |  122 +
 src/libpts/plugins/imv_swid/imv_swid_rest.h        |   63 +
 src/libpts/plugins/imv_swid/imv_swid_state.c       |  172 +-
 src/libpts/plugins/imv_swid/imv_swid_state.h       |   63 +-
 src/libpts/pts/components/ita/ita_comp_ima.c       |  694 +++--
 src/libpts/pts/components/ita/ita_comp_tboot.c     |   95 +-
 src/libpts/pts/components/ita/ita_comp_tgrub.c     |    7 +-
 src/libpts/pts/components/pts_component.h          |    5 +-
 src/libpts/pts/pts.c                               |  152 +-
 src/libpts/pts/pts.h                               |   22 +-
 src/libpts/pts/pts_database.c                      |  172 +-
 src/libpts/pts/pts_database.h                      |   62 +-
 src/libpts/pts/pts_file_meas.c                     |  117 +-
 src/libpts/pts/pts_file_meas.h                     |    5 +-
 src/libpts/pts/pts_ima_bios_list.c                 |  294 +++
 src/libpts/pts/pts_ima_bios_list.h                 |   74 +
 src/libpts/pts/pts_ima_event_list.c                |  330 +++
 src/libpts/pts/pts_ima_event_list.h                |   80 +
 src/libpts/pts/pts_meas_algo.c                     |    7 +-
 src/libpts/pts/pts_meas_algo.h                     |    4 +-
 src/libpts/swid/swid_error.c                       |    2 +-
 src/libpts/swid/swid_inventory.c                   |  238 +-
 src/libpts/swid/swid_inventory.h                   |    9 +-
 src/libpts/swid/swid_tag.c                         |   40 +-
 src/libpts/swid/swid_tag.h                         |   19 +-
 src/libpts/swid/swid_tag_id.c                      |   42 +-
 src/libpts/swid/swid_tag_id.h                      |   19 +-
 src/libpts/tcg/swid/tcg_swid_attr_req.c            |    7 +-
 src/libpts/tcg/swid/tcg_swid_attr_req.h            |    4 +-
 src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c     |   66 +-
 src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h     |   25 +-
 src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c        |   60 +-
 src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h        |   24 +-
 src/libpttls/Makefile.am                           |    4 +
 src/libpttls/Makefile.in                           |   15 +-
 src/libpttls/pt_tls.h                              |    2 +-
 src/libradius/Makefile.in                          |    6 +-
 src/libsimaka/Makefile.in                          |    6 +-
 src/libsimaka/simaka_message.h                     |    2 +-
 src/libstrongswan/Android.mk                       |   30 +-
 src/libstrongswan/AndroidConfigLocal.h             |    2 -
 src/libstrongswan/Makefile.am                      |   70 +-
 src/libstrongswan/Makefile.in                      |  686 +++--
 src/libstrongswan/asn1/asn1.c                      |    2 +-
 src/libstrongswan/asn1/oid.h                       |    2 +-
 src/libstrongswan/asn1/oid.pl                      |    2 +-
 src/libstrongswan/collections/array.c              |    2 +-
 src/libstrongswan/collections/dictionary.h         |   55 +
 src/libstrongswan/collections/enumerator.c         |  103 +-
 src/libstrongswan/collections/enumerator.h         |   37 +-
 src/libstrongswan/collections/hashtable.c          |   39 +-
 src/libstrongswan/collections/hashtable.h          |    9 +
 src/libstrongswan/credentials/auth_cfg.c           |    2 +-
 src/libstrongswan/credentials/certificates/crl.h   |   28 +-
 src/libstrongswan/credentials/cred_encoding.h      |    2 +
 src/libstrongswan/credentials/sets/cert_cache.c    |    1 -
 src/libstrongswan/credentials/sets/mem_cred.c      |   76 +-
 src/libstrongswan/crypto/crypto_factory.c          |   18 +-
 src/libstrongswan/crypto/crypto_tester.c           |    8 +-
 src/libstrongswan/crypto/transform.h               |    2 +-
 src/libstrongswan/eap/eap.c                        |   11 +-
 src/libstrongswan/eap/eap.h                        |    1 +
 src/libstrongswan/fetcher/fetcher.h                |    6 +
 src/libstrongswan/fetcher/fetcher_manager.c        |    4 +
 src/libstrongswan/ipsec/ipsec_types.h              |    6 +-
 src/libstrongswan/library.c                        |   16 +-
 src/libstrongswan/library.h                        |    2 +-
 src/libstrongswan/networking/host.h                |    4 +-
 src/libstrongswan/networking/host_resolver.c       |    2 -
 src/libstrongswan/networking/streams/stream.c      |  133 +-
 src/libstrongswan/networking/streams/stream.h      |   51 -
 .../networking/streams/stream_manager.c            |   19 +-
 .../networking/streams/stream_service.c            |   99 +-
 .../networking/streams/stream_service.h            |   19 -
 .../networking/streams/stream_service_tcp.c        |   64 +
 .../networking/streams/stream_service_tcp.h        |   33 +
 .../networking/streams/stream_service_unix.c       |   75 +
 .../networking/streams/stream_service_unix.h       |   42 +
 src/libstrongswan/networking/streams/stream_tcp.c  |   99 +
 src/libstrongswan/networking/streams/stream_tcp.h  |   52 +
 src/libstrongswan/networking/streams/stream_unix.c |   69 +
 src/libstrongswan/networking/streams/stream_unix.h |   48 +
 src/libstrongswan/networking/tun_device.c          |  124 +-
 src/libstrongswan/plugins/acert/Makefile.am        |    2 +-
 src/libstrongswan/plugins/acert/Makefile.in        |    8 +-
 src/libstrongswan/plugins/aes/Makefile.am          |    2 +-
 src/libstrongswan/plugins/aes/Makefile.in          |    8 +-
 src/libstrongswan/plugins/aes/aes_crypter.c        |  687 +----
 src/libstrongswan/plugins/af_alg/Makefile.am       |    2 +-
 src/libstrongswan/plugins/af_alg/Makefile.in       |    8 +-
 src/libstrongswan/plugins/agent/Makefile.am        |    2 +-
 src/libstrongswan/plugins/agent/Makefile.in        |    8 +-
 src/libstrongswan/plugins/blowfish/Makefile.am     |    2 +-
 src/libstrongswan/plugins/blowfish/Makefile.in     |    8 +-
 src/libstrongswan/plugins/ccm/Makefile.am          |    2 +-
 src/libstrongswan/plugins/ccm/Makefile.in          |    8 +-
 src/libstrongswan/plugins/cmac/Makefile.am         |    2 +-
 src/libstrongswan/plugins/cmac/Makefile.in         |    8 +-
 src/libstrongswan/plugins/constraints/Makefile.am  |    2 +-
 src/libstrongswan/plugins/constraints/Makefile.in  |    8 +-
 src/libstrongswan/plugins/ctr/Makefile.am          |    2 +-
 src/libstrongswan/plugins/ctr/Makefile.in          |    8 +-
 src/libstrongswan/plugins/curl/Makefile.am         |    2 +-
 src/libstrongswan/plugins/curl/Makefile.in         |    8 +-
 src/libstrongswan/plugins/curl/curl_fetcher.c      |   21 +-
 src/libstrongswan/plugins/des/Makefile.am          |    2 +-
 src/libstrongswan/plugins/des/Makefile.in          |    8 +-
 src/libstrongswan/plugins/dnskey/Makefile.am       |    2 +-
 src/libstrongswan/plugins/dnskey/Makefile.in       |    8 +-
 src/libstrongswan/plugins/fips_prf/Makefile.am     |    2 +-
 src/libstrongswan/plugins/fips_prf/Makefile.in     |    8 +-
 src/libstrongswan/plugins/gcm/Makefile.am          |    2 +-
 src/libstrongswan/plugins/gcm/Makefile.in          |    8 +-
 src/libstrongswan/plugins/gcrypt/Makefile.am       |    2 +-
 src/libstrongswan/plugins/gcrypt/Makefile.in       |    8 +-
 src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c   |   54 +-
 src/libstrongswan/plugins/gmp/Makefile.am          |    2 +-
 src/libstrongswan/plugins/gmp/Makefile.in          |    8 +-
 src/libstrongswan/plugins/hmac/Makefile.am         |    2 +-
 src/libstrongswan/plugins/hmac/Makefile.in         |    8 +-
 src/libstrongswan/plugins/keychain/Makefile.am     |    2 +-
 src/libstrongswan/plugins/keychain/Makefile.in     |    8 +-
 src/libstrongswan/plugins/ldap/Makefile.am         |    2 +-
 src/libstrongswan/plugins/ldap/Makefile.in         |    8 +-
 src/libstrongswan/plugins/md4/Makefile.am          |    2 +-
 src/libstrongswan/plugins/md4/Makefile.in          |    8 +-
 src/libstrongswan/plugins/md5/Makefile.am          |    2 +-
 src/libstrongswan/plugins/md5/Makefile.in          |    8 +-
 src/libstrongswan/plugins/mysql/Makefile.am        |    2 +-
 src/libstrongswan/plugins/mysql/Makefile.in        |    8 +-
 src/libstrongswan/plugins/mysql/mysql_database.c   |   12 +-
 src/libstrongswan/plugins/mysql/mysql_database.h   |    1 +
 src/libstrongswan/plugins/nonce/Makefile.am        |    2 +-
 src/libstrongswan/plugins/nonce/Makefile.in        |    8 +-
 src/libstrongswan/plugins/ntru/Makefile.am         |    5 +-
 src/libstrongswan/plugins/ntru/Makefile.in         |    9 +-
 src/libstrongswan/plugins/openssl/Makefile.am      |    4 +-
 src/libstrongswan/plugins/openssl/Makefile.in      |   13 +-
 src/libstrongswan/plugins/openssl/openssl_plugin.c |   21 +-
 src/libstrongswan/plugins/openssl/openssl_rng.c    |    2 +
 src/libstrongswan/plugins/openssl/openssl_util.h   |    6 +
 src/libstrongswan/plugins/padlock/Makefile.am      |    2 +-
 src/libstrongswan/plugins/padlock/Makefile.in      |    8 +-
 src/libstrongswan/plugins/pem/Makefile.am          |    2 +-
 src/libstrongswan/plugins/pem/Makefile.in          |    8 +-
 src/libstrongswan/plugins/pgp/Makefile.am          |    2 +-
 src/libstrongswan/plugins/pgp/Makefile.in          |    8 +-
 src/libstrongswan/plugins/pgp/pgp_builder.c        |    3 +-
 src/libstrongswan/plugins/pkcs1/Makefile.am        |    2 +-
 src/libstrongswan/plugins/pkcs1/Makefile.in        |    8 +-
 src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c    |   47 +-
 src/libstrongswan/plugins/pkcs11/Makefile.am       |    2 +-
 src/libstrongswan/plugins/pkcs11/Makefile.in       |    8 +-
 src/libstrongswan/plugins/pkcs11/pkcs11_library.h  |    2 +-
 src/libstrongswan/plugins/pkcs12/Makefile.am       |    2 +-
 src/libstrongswan/plugins/pkcs12/Makefile.in       |    8 +-
 src/libstrongswan/plugins/pkcs7/Makefile.am        |    2 +-
 src/libstrongswan/plugins/pkcs7/Makefile.in        |    8 +-
 src/libstrongswan/plugins/pkcs8/Makefile.am        |    2 +-
 src/libstrongswan/plugins/pkcs8/Makefile.in        |    8 +-
 src/libstrongswan/plugins/plugin_loader.c          |    2 +
 src/libstrongswan/plugins/pubkey/Makefile.am       |    2 +-
 src/libstrongswan/plugins/pubkey/Makefile.in       |    8 +-
 src/libstrongswan/plugins/random/Makefile.am       |    2 +-
 src/libstrongswan/plugins/random/Makefile.in       |    8 +-
 src/libstrongswan/plugins/random/random_plugin.c   |    5 +
 src/libstrongswan/plugins/rc2/Makefile.am          |    2 +-
 src/libstrongswan/plugins/rc2/Makefile.in          |    8 +-
 src/libstrongswan/plugins/rdrand/Makefile.am       |    2 +-
 src/libstrongswan/plugins/rdrand/Makefile.in       |    8 +-
 src/libstrongswan/plugins/revocation/Makefile.am   |    2 +-
 src/libstrongswan/plugins/revocation/Makefile.in   |    8 +-
 src/libstrongswan/plugins/sha1/Makefile.am         |    2 +-
 src/libstrongswan/plugins/sha1/Makefile.in         |    8 +-
 src/libstrongswan/plugins/sha1/sha1_hasher.c       |    4 +-
 src/libstrongswan/plugins/sha1/sha1_prf.c          |    3 +-
 src/libstrongswan/plugins/sha2/Makefile.am         |    2 +-
 src/libstrongswan/plugins/sha2/Makefile.in         |    8 +-
 src/libstrongswan/plugins/soup/Makefile.am         |    2 +-
 src/libstrongswan/plugins/soup/Makefile.in         |    8 +-
 src/libstrongswan/plugins/soup/soup_fetcher.c      |   16 +-
 src/libstrongswan/plugins/sqlite/Makefile.am       |    2 +-
 src/libstrongswan/plugins/sqlite/Makefile.in       |    8 +-
 src/libstrongswan/plugins/sqlite/sqlite_database.c |   10 +-
 src/libstrongswan/plugins/sshkey/Makefile.am       |    2 +-
 src/libstrongswan/plugins/sshkey/Makefile.in       |    8 +-
 src/libstrongswan/plugins/sshkey/sshkey_builder.c  |   49 +-
 src/libstrongswan/plugins/sshkey/sshkey_builder.h  |   15 +-
 src/libstrongswan/plugins/sshkey/sshkey_plugin.c   |    4 +-
 src/libstrongswan/plugins/test_vectors/Makefile.am |    2 +-
 src/libstrongswan/plugins/test_vectors/Makefile.in |    8 +-
 src/libstrongswan/plugins/unbound/Makefile.am      |    2 +-
 src/libstrongswan/plugins/unbound/Makefile.in      |    8 +-
 src/libstrongswan/plugins/unbound/unbound_rr.c     |    4 +-
 src/libstrongswan/plugins/winhttp/Makefile.am      |   18 +
 src/libstrongswan/plugins/winhttp/Makefile.in      |  766 ++++++
 .../plugins/winhttp/winhttp_fetcher.c              |  396 +++
 .../plugins/winhttp/winhttp_fetcher.h              |   46 +
 src/libstrongswan/plugins/winhttp/winhttp_plugin.c |   74 +
 src/libstrongswan/plugins/winhttp/winhttp_plugin.h |   42 +
 src/libstrongswan/plugins/x509/Makefile.am         |    2 +-
 src/libstrongswan/plugins/x509/Makefile.in         |    8 +-
 src/libstrongswan/plugins/x509/x509_ac.c           |   25 +-
 src/libstrongswan/plugins/x509/x509_cert.c         |    5 -
 .../plugins/x509/x509_ocsp_response.c              |   25 +-
 src/libstrongswan/plugins/xcbc/Makefile.am         |    2 +-
 src/libstrongswan/plugins/xcbc/Makefile.in         |    8 +-
 src/libstrongswan/processing/processor.c           |   12 +-
 src/libstrongswan/processing/watcher.c             |  118 +-
 src/libstrongswan/selectors/traffic_selector.c     |    7 +-
 src/libstrongswan/settings/settings.c              |  944 +++++++
 src/libstrongswan/settings/settings.h              |  353 +++
 src/libstrongswan/settings/settings_lexer.c        | 2686 +++++++++++++++++++
 src/libstrongswan/settings/settings_lexer.l        |  201 ++
 src/libstrongswan/settings/settings_parser.c       | 1747 +++++++++++++
 src/libstrongswan/settings/settings_parser.h       |   79 +
 src/libstrongswan/settings/settings_parser.y       |  290 +++
 src/libstrongswan/settings/settings_types.c        |  321 +++
 src/libstrongswan/settings/settings_types.h        |  177 ++
 src/libstrongswan/tests/Makefile.am                |    3 +-
 src/libstrongswan/tests/Makefile.in                |   27 +-
 src/libstrongswan/tests/suites/test_asn1.c         |    4 +-
 src/libstrongswan/tests/suites/test_chunk.c        |   12 +-
 .../tests/suites/test_crypto_factory.c             |  312 +++
 src/libstrongswan/tests/suites/test_enum.c         |   52 +-
 src/libstrongswan/tests/suites/test_fetch_http.c   |   84 +-
 src/libstrongswan/tests/suites/test_host.c         |    4 +-
 .../tests/suites/test_identification.c             |    8 +-
 src/libstrongswan/tests/suites/test_settings.c     |  435 +++-
 src/libstrongswan/tests/suites/test_stream.c       |    3 +-
 src/libstrongswan/tests/suites/test_threading.c    |    6 +-
 src/libstrongswan/tests/suites/test_utils.c        |   82 +-
 src/libstrongswan/tests/suites/test_watcher.c      |    9 +-
 src/libstrongswan/tests/test_runner.c              |   67 +-
 src/libstrongswan/tests/test_runner.h              |    8 +-
 src/libstrongswan/tests/test_suite.c               |  232 +-
 src/libstrongswan/tests/test_suite.h               |   46 +-
 src/libstrongswan/tests/tests.c                    |   10 +-
 src/libstrongswan/tests/tests.h                    |    1 +
 src/libstrongswan/threading/thread.c               |    3 +
 src/libstrongswan/threading/windows/mutex.c        |  196 ++
 src/libstrongswan/threading/windows/rwlock.c       |  220 ++
 src/libstrongswan/threading/windows/semaphore.c    |  101 +
 src/libstrongswan/threading/windows/spinlock.c     |   79 +
 src/libstrongswan/threading/windows/thread.c       |  677 +++++
 src/libstrongswan/threading/windows/thread.h       |   74 +
 src/libstrongswan/threading/windows/thread_value.c |  178 ++
 src/libstrongswan/utils/backtrace.c                |  253 +-
 src/libstrongswan/utils/capabilities.c             |   40 +-
 src/libstrongswan/utils/chunk.c                    |   50 +-
 src/libstrongswan/utils/chunk.h                    |   11 +
 src/libstrongswan/utils/debug.h                    |    2 +-
 src/libstrongswan/utils/enum.c                     |    8 +-
 src/libstrongswan/utils/enum.h                     |   25 +-
 src/libstrongswan/utils/identification.c           |   21 +-
 src/libstrongswan/utils/leak_detective.c           |    8 +-
 src/libstrongswan/utils/optionsfrom.c              |    9 +-
 src/libstrongswan/utils/parser_helper.c            |  261 ++
 src/libstrongswan/utils/parser_helper.h            |  161 ++
 .../utils/printf_hook/printf_hook_builtin.c        |  124 +
 src/libstrongswan/utils/settings.c                 | 1520 -----------
 src/libstrongswan/utils/settings.h                 |  348 ---
 src/libstrongswan/utils/test.c                     |   71 +-
 src/libstrongswan/utils/test.h                     |   18 +-
 src/libstrongswan/utils/utils.c                    |  279 +-
 src/libstrongswan/utils/utils.h                    |  173 +-
 src/libstrongswan/utils/utils/strerror.c           |  122 +-
 src/libstrongswan/utils/utils/strerror.h           |   10 +
 src/libstrongswan/utils/windows.c                  |  641 +++++
 src/libstrongswan/utils/windows.h                  |  584 +++++
 src/libtls/Makefile.am                             |    4 +
 src/libtls/Makefile.in                             |   16 +-
 src/libtls/tests/Makefile.am                       |    2 +-
 src/libtls/tests/Makefile.in                       |    8 +-
 src/libtls/tls.c                                   |    8 +-
 src/libtls/tls_crypto.c                            |    4 +-
 src/libtls/tls_eap.c                               |  113 +-
 src/libtls/tls_eap.h                               |    4 +-
 src/libtnccs/Makefile.am                           |    6 +-
 src/libtnccs/Makefile.in                           |   56 +-
 src/libtnccs/plugins/tnc_imc/Makefile.am           |    2 +-
 src/libtnccs/plugins/tnc_imc/Makefile.in           |    8 +-
 src/libtnccs/plugins/tnc_imc/tnc_imc.c             |    6 +-
 src/libtnccs/plugins/tnc_imv/Makefile.am           |    2 +-
 src/libtnccs/plugins/tnc_imv/Makefile.in           |    8 +-
 src/libtnccs/plugins/tnc_imv/tnc_imv.c             |    2 +
 src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c     |   13 +-
 src/libtnccs/plugins/tnc_tnccs/Makefile.am         |    2 +-
 src/libtnccs/plugins/tnc_tnccs/Makefile.in         |    8 +-
 src/libtnccs/plugins/tnccs_11/Makefile.am          |    2 +-
 src/libtnccs/plugins/tnccs_11/Makefile.in          |    8 +-
 .../plugins/tnccs_11/messages/tnccs_error_msg.c    |    5 +-
 src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c |    6 +-
 src/libtnccs/plugins/tnccs_20/Makefile.am          |    2 +-
 src/libtnccs/plugins/tnccs_20/Makefile.in          |    8 +-
 src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c |   13 +-
 src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h |    3 +
 .../plugins/tnccs_20/messages/ietf/pb_pa_msg.c     |    2 +-
 .../plugins/tnccs_20/messages/ietf/pb_pa_msg.h     |    2 +
 src/libtnccs/plugins/tnccs_20/tnccs_20.c           |   38 +-
 src/libtnccs/plugins/tnccs_dynamic/Makefile.am     |    2 +-
 src/libtnccs/plugins/tnccs_dynamic/Makefile.in     |    8 +-
 src/libtnccs/tnc/tnc.c                             |    8 +-
 src/libtncif/Makefile.in                           |    6 +-
 src/manager/Makefile.am                            |    2 +-
 src/manager/Makefile.in                            |    8 +-
 src/medsrv/Makefile.am                             |    2 +-
 src/medsrv/Makefile.in                             |    8 +-
 src/pki/Makefile.in                                |    6 +-
 src/pki/command.c                                  |    2 +-
 src/pki/commands/acert.c                           |    5 +-
 src/pki/commands/gen.c                             |    2 +-
 src/pki/commands/issue.c                           |    5 +-
 src/pki/commands/keyid.c                           |    1 +
 src/pki/commands/pkcs7.c                           |    1 +
 src/pki/commands/print.c                           |    1 +
 src/pki/commands/pub.c                             |    2 +
 src/pki/commands/req.c                             |    5 +-
 src/pki/commands/self.c                            |    5 +-
 src/pki/commands/signcrl.c                         |    4 +-
 src/pki/commands/verify.c                          |  135 +-
 src/pki/man/Makefile.in                            |    6 +-
 src/pki/man/pki---verify.1.in                      |   16 +-
 src/pki/pki.c                                      |  106 +-
 src/pki/pki.h                                      |    5 +
 src/pool/Makefile.in                               |    6 +-
 src/pt-tls-client/Makefile.am                      |    2 +-
 src/pt-tls-client/Makefile.in                      |    8 +-
 src/pt-tls-client/pt-tls-client.c                  |  118 +-
 src/scepclient/Android.mk                          |   28 +
 src/scepclient/Makefile.am                         |    1 +
 src/scepclient/Makefile.in                         |    7 +-
 src/scepclient/scepclient.c                        |    2 +-
 src/starter/Android.mk                             |   12 +-
 src/starter/Makefile.am                            |   28 +-
 src/starter/Makefile.in                            |  321 ++-
 src/starter/README                                 |  101 -
 src/starter/args.c                                 |  357 +--
 src/starter/args.h                                 |   17 +-
 src/starter/confread.c                             |  999 +++----
 src/starter/confread.h                             |   43 +-
 src/starter/ipsec-parser.h                         |   55 -
 src/starter/keywords.c                             |   47 +-
 src/starter/keywords.h                             |   13 +-
 src/starter/keywords.txt                           |    1 +
 src/starter/lexer.c                                | 1992 --------------
 src/starter/lexer.l                                |  215 --
 src/starter/parser.c                               | 1870 -------------
 src/starter/parser.h                               |  106 -
 src/starter/parser.y                               |  272 --
 src/starter/parser/conf_parser.c                   |  667 +++++
 src/starter/parser/conf_parser.h                   |  122 +
 src/starter/parser/lexer.c                         | 2737 ++++++++++++++++++++
 src/starter/parser/lexer.l                         |  205 ++
 src/starter/parser/parser.c                        | 1700 ++++++++++++
 src/starter/parser/parser.h                        |   86 +
 src/starter/parser/parser.y                        |  254 ++
 src/starter/starter.c                              |   27 +
 src/starter/starterstroke.c                        |   50 +-
 src/starter/tests/Makefile.am                      |   19 +
 src/starter/tests/Makefile.in                      |  856 ++++++
 src/starter/tests/starter_tests.c                  |   43 +
 src/starter/tests/starter_tests.h                  |   16 +
 src/starter/tests/suites/test_parser.c             |  575 ++++
 src/stroke/Makefile.in                             |    6 +-
 src/stroke/stroke.c                                |  340 +--
 src/stroke/stroke_msg.h                            |    1 +
 src/swanctl/Makefile.am                            |   66 +
 src/swanctl/Makefile.in                            |  981 +++++++
 src/swanctl/command.c                              |  309 +++
 src/swanctl/command.h                              |  108 +
 src/swanctl/commands/initiate.c                    |  132 +
 src/swanctl/commands/install.c                     |  125 +
 src/swanctl/commands/list_certs.c                  |  670 +++++
 src/swanctl/commands/list_conns.c                  |  242 ++
 src/swanctl/commands/list_pols.c                   |  210 ++
 src/swanctl/commands/list_pools.c                  |  101 +
 src/swanctl/commands/list_sas.c                    |  366 +++
 src/swanctl/commands/load_conns.c                  |  419 +++
 src/swanctl/commands/load_creds.c                  |  574 ++++
 src/swanctl/commands/load_pools.c                  |  292 +++
 src/swanctl/commands/log.c                         |  101 +
 src/swanctl/commands/stats.c                       |  118 +
 src/swanctl/commands/terminate.c                   |  157 ++
 src/swanctl/commands/version.c                     |   96 +
 src/swanctl/swanctl.8.in                           |   83 +
 src/swanctl/swanctl.c                              |   57 +
 src/swanctl/swanctl.conf                           |  306 +++
 src/swanctl/swanctl.conf.5.head.in                 |   24 +
 src/swanctl/swanctl.conf.5.main                    |  957 +++++++
 src/swanctl/swanctl.conf.5.tail.in                 |   10 +
 src/swanctl/swanctl.h                              |   69 +
 src/swanctl/swanctl.opt                            |  779 ++++++
 testing/Makefile.in                                |    6 +-
 testing/config/kernel/config-3.15                  | 2083 +++++++++++++++
 testing/do-tests                                   |   96 +-
 testing/hosts/alice/etc/swanctl/rsa/aliceKey.pem   |   27 +
 testing/hosts/alice/etc/swanctl/x509/aliceCert.pem |   25 +
 .../alice/etc/swanctl/x509ca/strongswanCert.pem    |   22 +
 testing/hosts/bob/etc/swanctl/rsa/bobKey.pem       |   27 +
 testing/hosts/bob/etc/swanctl/x509/bobCert.pem     |   25 +
 .../bob/etc/swanctl/x509ca/strongswanCert.pem      |   22 +
 testing/hosts/carol/etc/swanctl/rsa/carolKey.pem   |   27 +
 testing/hosts/carol/etc/swanctl/x509/carolCert.pem |   25 +
 .../carol/etc/swanctl/x509ca/strongswanCert.pem    |   22 +
 testing/hosts/dave/etc/swanctl/rsa/daveKey.pem     |   27 +
 testing/hosts/dave/etc/swanctl/x509/daveCert.pem   |   25 +
 .../dave/etc/swanctl/x509ca/strongswanCert.pem     |   22 +
 testing/hosts/default/etc/hosts                    |    2 +-
 testing/hosts/default/etc/init.d/charon            |  156 ++
 testing/hosts/moon/etc/swanctl/rsa/moonKey.pem     |   27 +
 testing/hosts/moon/etc/swanctl/x509/moonCert.pem   |   25 +
 .../moon/etc/swanctl/x509ca/strongswanCert.pem     |   22 +
 testing/hosts/sun/etc/swanctl/rsa/sunKey.pem       |   27 +
 testing/hosts/sun/etc/swanctl/x509/sunCert.pem     |   25 +
 .../sun/etc/swanctl/x509ca/strongswanCert.pem      |   22 +
 testing/hosts/venus/etc/swanctl/rsa/venusKey.pem   |   27 +
 testing/hosts/venus/etc/swanctl/x509/venusCert.pem |   24 +
 .../venus/etc/swanctl/x509ca/strongswanCert.pem    |   22 +
 testing/hosts/winnetou/etc/openssl/index.txt       |    5 +-
 testing/hosts/winnetou/etc/openssl/index.txt.old   |    6 +-
 testing/hosts/winnetou/etc/openssl/newcerts/29.pem |   25 +
 testing/hosts/winnetou/etc/openssl/serial          |    2 +-
 testing/hosts/winnetou/etc/openssl/serial.old      |    2 +-
 testing/scripts/build-baseimage                    |    4 +-
 testing/scripts/build-guestimages                  |    9 +-
 testing/scripts/recipes/014_swid_generator.mk      |   16 +
 testing/scripts/recipes/015_strongTNC.mk           |   22 +
 testing/testing.conf                               |   12 +-
 .../hosts/moon/etc/ipsec.d/aacerts/aa.pem          |   19 +
 .../etc/ipsec.d/acerts/carol-sales-finance.pem     |   18 +
 .../moon/etc/ipsec.d/acerts/dave-marketing.pem     |   18 +
 .../moon/etc/ipsec.d/acerts/dave-sales-expired.pem |   18 +
 .../hosts/moon/etc/ipsec.d/private/aa.pem          |   27 +
 .../etc/ipsec.d/acerts/carol-finance-expired.pem   |   18 +
 .../hosts/carol/etc/ipsec.d/acerts/carol-sales.pem |   18 +
 .../hosts/moon/etc/ipsec.d/aacerts/aa.pem          |   19 +
 .../hosts/moon/etc/ipsec.d/private/aa.pem          |   27 +
 .../hosts/carol/etc/ipsec.d/acerts/carol-sales.pem |   18 +
 .../dave/etc/ipsec.d/acerts/dave-expired-aa.pem    |   18 +
 .../dave/etc/ipsec.d/acerts/dave-marketing.pem     |   18 +
 .../hosts/moon/etc/ipsec.d/aacerts/aa-expired.pem  |   19 +
 .../hosts/moon/etc/ipsec.d/aacerts/aa.pem          |   19 +
 .../hosts/moon/etc/ipsec.d/private/aa-expired.pem  |   27 +
 .../hosts/moon/etc/ipsec.d/private/aa.pem          |   27 +
 .../ikev2/shunt-policies-nat-rw/description.txt    |    7 +
 .../tests/ikev2/shunt-policies-nat-rw/evaltest.dat |   12 +
 .../hosts/alice/etc/ipsec.conf                     |   27 +
 .../hosts/alice/etc/strongswan.conf                |    7 +
 .../shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf |   20 +
 .../hosts/sun/etc/iptables.rules                   |   24 +
 .../hosts/sun/etc/strongswan.conf                  |    5 +
 .../hosts/venus/etc/ipsec.conf                     |   27 +
 .../hosts/venus/etc/strongswan.conf                |    7 +
 .../tests/ikev2/shunt-policies-nat-rw/posttest.dat |    5 +
 .../tests/ikev2/shunt-policies-nat-rw/pretest.dat  |   11 +
 .../tests/ikev2/shunt-policies-nat-rw/test.conf    |   21 +
 testing/tests/ikev2/shunt-policies/description.txt |   11 -
 testing/tests/ikev2/shunt-policies/evaltest.dat    |   16 -
 .../ikev2/shunt-policies/hosts/moon/etc/ipsec.conf |   40 -
 .../shunt-policies/hosts/moon/etc/iptables.rules   |   32 -
 .../shunt-policies/hosts/moon/etc/strongswan.conf  |    7 -
 .../ikev2/shunt-policies/hosts/sun/etc/ipsec.conf  |   22 -
 .../shunt-policies/hosts/sun/etc/strongswan.conf   |    6 -
 testing/tests/ikev2/shunt-policies/posttest.dat    |    5 -
 testing/tests/ikev2/shunt-policies/pretest.dat     |    6 -
 testing/tests/ikev2/shunt-policies/test.conf       |   21 -
 .../carol/etc/ipsec.d/certs/carolCert-002.pem      |   34 +-
 .../carol/etc/ipsec.d/private/carolKey-002.pem     |   50 +-
 .../hosts/moon/etc/ipsec.d/certs/moonCert.asc      |   15 +
 .../hosts/moon/etc/ipsec.d/certs/sunCert.asc       |   15 +
 .../hosts/moon/etc/ipsec.d/private/moonKey.asc     |   19 +
 .../hosts/sun/etc/ipsec.d/certs/moonCert.asc       |   15 +
 .../hosts/sun/etc/ipsec.d/certs/sunCert.asc        |   15 +
 .../hosts/sun/etc/ipsec.d/private/sunKey.asc       |   19 +
 testing/tests/pfkey/compress/description.txt       |    4 +
 testing/tests/pfkey/compress/evaltest.dat          |   12 +
 .../pfkey/compress/hosts/carol/etc/ipsec.conf      |   21 +
 .../pfkey/compress/hosts/carol/etc/strongswan.conf |    5 +
 .../tests/pfkey/compress/hosts/moon/etc/ipsec.conf |   21 +
 .../pfkey/compress/hosts/moon/etc/strongswan.conf  |    5 +
 testing/tests/pfkey/compress/posttest.dat          |    4 +
 testing/tests/pfkey/compress/pretest.dat           |    6 +
 testing/tests/pfkey/compress/test.conf             |   22 +
 .../pfkey/shunt-policies-nat-rw/description.txt    |    7 +
 .../tests/pfkey/shunt-policies-nat-rw/evaltest.dat |   12 +
 .../hosts/alice/etc/ipsec.conf                     |   27 +
 .../hosts/alice/etc/strongswan.conf                |    7 +
 .../shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf |   20 +
 .../hosts/sun/etc/iptables.rules                   |   24 +
 .../hosts/sun/etc/strongswan.conf                  |    5 +
 .../hosts/venus/etc/ipsec.conf                     |   27 +
 .../hosts/venus/etc/strongswan.conf                |    7 +
 .../tests/pfkey/shunt-policies-nat-rw/posttest.dat |    5 +
 .../tests/pfkey/shunt-policies-nat-rw/pretest.dat  |   11 +
 .../tests/pfkey/shunt-policies-nat-rw/test.conf    |   21 +
 testing/tests/pfkey/shunt-policies/description.txt |   11 -
 testing/tests/pfkey/shunt-policies/evaltest.dat    |   20 -
 .../pfkey/shunt-policies/hosts/moon/etc/ipsec.conf |   40 -
 .../shunt-policies/hosts/moon/etc/iptables.rules   |   32 -
 .../shunt-policies/hosts/moon/etc/strongswan.conf  |    7 -
 .../pfkey/shunt-policies/hosts/sun/etc/ipsec.conf  |   22 -
 .../shunt-policies/hosts/sun/etc/strongswan.conf   |    6 -
 testing/tests/pfkey/shunt-policies/posttest.dat    |    5 -
 testing/tests/pfkey/shunt-policies/pretest.dat     |    6 -
 testing/tests/pfkey/shunt-policies/test.conf       |   21 -
 .../sql/shunt-policies-nat-rw/description.txt      |    7 +
 .../tests/sql/shunt-policies-nat-rw/evaltest.dat   |   12 +
 .../hosts/alice/etc/ipsec.conf                     |    3 +
 .../hosts/alice/etc/ipsec.d/data.sql               |  199 ++
 .../hosts/alice}/etc/ipsec.secrets                 |    0
 .../hosts/alice/etc/strongswan.conf                |   12 +
 .../shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf |    3 +
 .../hosts/sun/etc/ipsec.d/data.sql                 |  195 ++
 .../hosts/sun/etc/ipsec.secrets                    |    0
 .../hosts/sun/etc/iptables.rules                   |   24 +
 .../hosts/sun/etc/strongswan.conf                  |   13 +
 .../hosts/venus/etc/ipsec.conf                     |    3 +
 .../hosts/venus/etc/ipsec.d/data.sql               |  199 ++
 .../hosts/venus}/etc/ipsec.secrets                 |    0
 .../hosts/venus/etc/strongswan.conf                |   12 +
 .../tests/sql/shunt-policies-nat-rw/posttest.dat   |    8 +
 .../tests/sql/shunt-policies-nat-rw/pretest.dat    |   20 +
 testing/tests/sql/shunt-policies-nat-rw/test.conf  |   21 +
 testing/tests/sql/shunt-policies/description.txt   |   11 -
 testing/tests/sql/shunt-policies/evaltest.dat      |   20 -
 .../sql/shunt-policies/hosts/moon/etc/ipsec.conf   |    5 -
 .../shunt-policies/hosts/moon/etc/ipsec.d/data.sql |  227 --
 .../shunt-policies/hosts/moon/etc/iptables.rules   |   32 -
 .../shunt-policies/hosts/moon/etc/strongswan.conf  |   11 -
 .../sql/shunt-policies/hosts/sun/etc/ipsec.conf    |    5 -
 .../shunt-policies/hosts/sun/etc/ipsec.d/data.sql  |  152 --
 .../shunt-policies/hosts/sun/etc/strongswan.conf   |   10 -
 testing/tests/sql/shunt-policies/posttest.dat      |    6 -
 testing/tests/sql/shunt-policies/pretest.dat       |   12 -
 testing/tests/swanctl/ip-pool-db/description.txt   |   10 +
 testing/tests/swanctl/ip-pool-db/evaltest.dat      |   23 +
 .../ip-pool-db/hosts/carol/etc/strongswan.conf     |   11 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   33 +
 .../ip-pool-db/hosts/dave/etc/strongswan.conf      |   11 +
 .../ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf |   33 +
 .../ip-pool-db/hosts/moon/etc/strongswan.conf      |   21 +
 .../ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf |   31 +
 testing/tests/swanctl/ip-pool-db/posttest.dat      |   11 +
 testing/tests/swanctl/ip-pool-db/pretest.dat       |   21 +
 testing/tests/swanctl/ip-pool-db/test.conf         |   21 +
 testing/tests/swanctl/ip-pool/description.txt      |   10 +
 testing/tests/swanctl/ip-pool/evaltest.dat         |   15 +
 .../ip-pool/hosts/carol/etc/strongswan.conf        |   13 +
 .../ip-pool/hosts/carol/etc/swanctl/swanctl.conf   |   33 +
 .../swanctl/ip-pool/hosts/dave/etc/strongswan.conf |   13 +
 .../ip-pool/hosts/dave/etc/swanctl/swanctl.conf    |   33 +
 .../swanctl/ip-pool/hosts/moon/etc/strongswan.conf |   13 +
 .../ip-pool/hosts/moon/etc/swanctl/swanctl.conf    |   37 +
 testing/tests/swanctl/ip-pool/posttest.dat         |    8 +
 testing/tests/swanctl/ip-pool/pretest.dat          |   15 +
 testing/tests/swanctl/ip-pool/test.conf            |   21 +
 testing/tests/swanctl/net2net-cert/description.txt |    6 +
 testing/tests/swanctl/net2net-cert/evaltest.dat    |    5 +
 .../net2net-cert/hosts/moon/etc/strongswan.conf    |   13 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   34 +
 .../net2net-cert/hosts/sun/etc/strongswan.conf     |   13 +
 .../hosts/sun/etc/swanctl/swanctl.conf             |   34 +
 testing/tests/swanctl/net2net-cert/posttest.dat    |    5 +
 testing/tests/swanctl/net2net-cert/pretest.dat     |    9 +
 .../net2net-cert}/test.conf                        |    0
 .../tests/swanctl/net2net-route/description.txt    |    9 +
 testing/tests/swanctl/net2net-route/evaltest.dat   |    7 +
 .../net2net-route/hosts/moon/etc/strongswan.conf   |   13 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   34 +
 .../net2net-route/hosts/sun/etc/strongswan.conf    |   13 +
 .../hosts/sun/etc/swanctl/swanctl.conf             |   34 +
 testing/tests/swanctl/net2net-route/posttest.dat   |    5 +
 testing/tests/swanctl/net2net-route/pretest.dat    |    9 +
 .../net2net-route}/test.conf                       |    0
 .../tests/swanctl/net2net-start/description.txt    |    6 +
 testing/tests/swanctl/net2net-start/evaltest.dat   |    5 +
 .../net2net-start/hosts/moon/etc/strongswan.conf   |   13 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   34 +
 .../net2net-start/hosts/sun/etc/strongswan.conf    |   13 +
 .../hosts/sun/etc/swanctl/swanctl.conf             |   34 +
 testing/tests/swanctl/net2net-start/posttest.dat   |    5 +
 testing/tests/swanctl/net2net-start/pretest.dat    |    9 +
 .../net2net-start}/test.conf                       |    0
 testing/tests/swanctl/rw-cert/description.txt      |    6 +
 testing/tests/swanctl/rw-cert/evaltest.dat         |   10 +
 .../rw-cert/hosts/carol/etc/strongswan.conf        |   13 +
 .../rw-cert/hosts/carol/etc/swanctl/swanctl.conf   |   32 +
 .../swanctl/rw-cert/hosts/dave/etc/strongswan.conf |   13 +
 .../rw-cert/hosts/dave/etc/swanctl/swanctl.conf    |   32 +
 .../swanctl/rw-cert/hosts/moon/etc/strongswan.conf |   13 +
 .../rw-cert/hosts/moon/etc/swanctl/swanctl.conf    |   30 +
 testing/tests/swanctl/rw-cert/posttest.dat         |    8 +
 testing/tests/swanctl/rw-cert/pretest.dat          |   14 +
 testing/tests/swanctl/rw-cert/test.conf            |   21 +
 testing/tests/swanctl/rw-psk-fqdn/description.txt  |    6 +
 testing/tests/swanctl/rw-psk-fqdn/evaltest.dat     |   10 +
 .../rw-psk-fqdn/hosts/carol/etc/strongswan.conf    |   13 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   41 +
 .../rw-psk-fqdn/hosts/dave/etc/strongswan.conf     |   13 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   39 +
 .../rw-psk-fqdn/hosts/moon/etc/strongswan.conf     |   13 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   41 +
 testing/tests/swanctl/rw-psk-fqdn/posttest.dat     |    8 +
 testing/tests/swanctl/rw-psk-fqdn/pretest.dat      |   17 +
 testing/tests/swanctl/rw-psk-fqdn/test.conf        |   21 +
 testing/tests/swanctl/rw-psk-ipv4/description.txt  |    6 +
 testing/tests/swanctl/rw-psk-ipv4/evaltest.dat     |   10 +
 .../rw-psk-ipv4/hosts/carol/etc/strongswan.conf    |   13 +
 .../hosts/carol/etc/swanctl/swanctl.conf           |   40 +
 .../rw-psk-ipv4/hosts/dave/etc/strongswan.conf     |   13 +
 .../hosts/dave/etc/swanctl/swanctl.conf            |   39 +
 .../rw-psk-ipv4/hosts/moon/etc/strongswan.conf     |   13 +
 .../hosts/moon/etc/swanctl/swanctl.conf            |   40 +
 testing/tests/swanctl/rw-psk-ipv4/posttest.dat     |    8 +
 testing/tests/swanctl/rw-psk-ipv4/pretest.dat      |   17 +
 testing/tests/swanctl/rw-psk-ipv4/test.conf        |   21 +
 .../tnccs-11-fhh/hosts/carol/etc/strongswan.conf   |    7 +
 .../tnccs-11-fhh/hosts/dave/etc/strongswan.conf    |    7 +
 .../tnccs-11-fhh/hosts/moon/etc/strongswan.conf    |    8 +-
 .../hosts/carol/etc/strongswan.conf                |    7 +
 .../hosts/dave/etc/strongswan.conf                 |    7 +
 .../hosts/alice/etc/pts/data1.sql                  |    2 +-
 .../hosts/carol/etc/strongswan.conf                |    7 +
 .../hosts/dave/etc/strongswan.conf                 |    7 +
 .../hosts/carol/etc/strongswan.conf                |    7 +
 .../tnccs-11-radius/hosts/dave/etc/strongswan.conf |    7 +
 .../tnc/tnccs-11/hosts/carol/etc/strongswan.conf   |    7 +
 .../tnc/tnccs-11/hosts/dave/etc/strongswan.conf    |    7 +
 .../tnc/tnccs-11/hosts/moon/etc/strongswan.conf    |    8 +-
 .../tnccs-20-block/hosts/carol/etc/strongswan.conf |    7 +-
 .../tnccs-20-block/hosts/dave/etc/strongswan.conf  |    5 +-
 .../tnccs-20-block/hosts/moon/etc/strongswan.conf  |    7 +-
 .../hosts/carol/etc/strongswan.conf                |    8 +-
 .../hosts/dave/etc/strongswan.conf                 |    7 +-
 .../hosts/moon/etc/strongswan.conf                 |    7 +-
 .../tnccs-20-fhh/hosts/carol/etc/strongswan.conf   |    8 +-
 .../tnccs-20-fhh/hosts/dave/etc/strongswan.conf    |    8 +-
 .../tnccs-20-fhh/hosts/moon/etc/strongswan.conf    |    7 +-
 testing/tests/tnc/tnccs-20-os-pts/description.txt  |   22 +
 testing/tests/tnc/tnccs-20-os-pts/evaltest.dat     |   20 +
 .../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                |   15 +
 .../tnc/tnccs-20-os-pts/hosts/carol/etc/tnc_config |    4 +
 .../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 +
 .../tnc/tnccs-20-os-pts/hosts/dave/etc/tnc_config  |    4 +
 .../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/pts/data1.sql   |   29 +
 .../tnccs-20-os-pts/hosts/moon/etc/strongswan.conf |   31 +
 .../hosts/moon/etc/tnc_config                      |    0
 testing/tests/tnc/tnccs-20-os-pts/posttest.dat     |    8 +
 testing/tests/tnc/tnccs-20-os-pts/pretest.dat      |   18 +
 testing/tests/tnc/tnccs-20-os-pts/test.conf        |   26 +
 testing/tests/tnc/tnccs-20-os/description.txt      |   13 +-
 testing/tests/tnc/tnccs-20-os/evaltest.dat         |    4 +-
 .../tnccs-20-os/hosts/carol/etc/strongswan.conf    |    8 +-
 .../tnc/tnccs-20-os/hosts/dave/etc/strongswan.conf |    7 +-
 .../tnc/tnccs-20-os/hosts/moon/etc/pts/data1.sql   |    4 +-
 .../tnc/tnccs-20-os/hosts/moon/etc/strongswan.conf |    7 +-
 testing/tests/tnc/tnccs-20-os/pretest.dat          |    2 +-
 .../description.txt                                |    0
 testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat    |   29 +
 .../alice/etc/apache2/sites-available/default      |   26 +
 .../tnccs-20-pdp-eap/hosts/alice/etc/ipsec.conf    |    9 +
 .../hosts/alice/etc/ipsec.d/certs/aaaCert.pem      |    0
 .../hosts/alice/etc/ipsec.d/private/aaaKey.pem     |    0
 .../hosts/alice/etc/ipsec.secrets                  |    0
 .../tnccs-20-pdp-eap/hosts/alice/etc/pts/data1.sql |   61 +
 .../hosts/alice/etc/strongTNC/settings.ini         |   19 +
 .../hosts/alice/etc/strongswan.conf                |   35 +
 .../hosts/alice/etc/tnc_config                     |    0
 .../tnccs-20-pdp-eap/hosts/carol/etc/ipsec.conf    |   23 +
 .../hosts/carol/etc/ipsec.secrets                  |    0
 .../hosts/carol/etc/strongswan.conf                |   18 +
 .../tnccs-20-pdp-eap/hosts/carol/etc/tnc_config    |    4 +
 .../tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.conf |   23 +
 .../hosts/dave/etc/ipsec.secrets                   |    0
 .../hosts/dave/etc/strongswan.conf                 |   30 +
 .../tnc/tnccs-20-pdp-eap/hosts/dave/etc/tnc_config |    4 +
 .../hosts/moon/etc/ipsec.conf                      |    0
 .../hosts/moon/etc/ipsec.secrets                   |    0
 .../hosts/moon/etc/iptables.rules                  |    0
 .../hosts/moon/etc/strongswan.conf                 |    0
 testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat    |    9 +
 testing/tests/tnc/tnccs-20-pdp-eap/pretest.dat     |   21 +
 .../{tnccs-20-pdp => tnccs-20-pdp-eap}/test.conf   |    0
 .../description.txt                                |    0
 testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat |   19 +
 .../alice/etc/apache2/sites-available/default      |   26 +
 .../tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.conf |    9 +
 .../hosts/alice/etc/ipsec.d/certs/aaaCert.pem      |    0
 .../hosts/alice/etc/ipsec.d/private/aaaKey.pem     |    0
 .../hosts/alice/etc/ipsec.secrets                  |    0
 .../hosts/alice/etc/iptables.rules                 |   24 +
 .../hosts/alice/etc/pts/data1.sql                  |   61 +
 .../hosts/alice/etc/strongTNC/settings.ini         |   19 +
 .../hosts/alice/etc/strongswan.conf                |   29 +
 .../hosts/alice/etc/tnc_config                     |    0
 .../hosts/carol/etc/ipsec.conf                     |    0
 .../hosts/carol/etc/ipsec.secrets                  |    0
 .../hosts/carol/etc/ipsec.sql                      |    0
 .../hosts/carol/etc/iptables.rules                 |    0
 .../hosts/carol/etc/pts/options                    |    6 +
 .../hosts/carol/etc/strongswan.conf                |    9 +
 .../hosts/carol/etc/tnc_config                     |    0
 .../hosts/dave/etc/ipsec.conf                      |    0
 .../hosts/dave/etc/ipsec.secrets                   |    0
 .../hosts/dave/etc/ipsec.sql                       |    0
 .../hosts/dave/etc/iptables.rules                  |    0
 .../tnccs-20-pdp-pt-tls/hosts/dave/etc/pts/options |    7 +
 .../hosts/dave/etc/strongswan.conf                 |   21 +
 .../hosts/dave/etc/tnc_config                      |    0
 testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat |    9 +
 testing/tests/tnc/tnccs-20-pdp-pt-tls/pretest.dat  |   23 +
 .../test.conf                                      |    0
 testing/tests/tnc/tnccs-20-pdp/evaltest.dat        |   22 -
 .../tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.conf    |    9 -
 .../tnccs-20-pdp/hosts/alice/etc/strongswan.conf   |   30 -
 .../tnc/tnccs-20-pdp/hosts/alice/etc/tnc_config    |    4 -
 .../tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.conf    |   23 -
 .../tnccs-20-pdp/hosts/carol/etc/strongswan.conf   |   18 -
 .../tnc/tnccs-20-pdp/hosts/carol/etc/tnc_config    |    4 -
 .../tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.conf     |   23 -
 .../tnccs-20-pdp/hosts/dave/etc/strongswan.conf    |   21 -
 .../tnc/tnccs-20-pdp/hosts/dave/etc/tnc_config     |    4 -
 testing/tests/tnc/tnccs-20-pdp/posttest.dat        |    7 -
 testing/tests/tnc/tnccs-20-pdp/pretest.dat         |   14 -
 testing/tests/tnc/tnccs-20-pt-tls/evaltest.dat     |   12 -
 .../tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.conf |    9 -
 .../tnccs-20-pt-tls/hosts/alice/etc/iptables.rules |   20 -
 .../tnccs-20-pt-tls/hosts/alice/etc/pts/data1.sql  |   61 -
 .../hosts/alice/etc/strongswan.conf                |   28 -
 .../tnccs-20-pt-tls/hosts/carol/etc/pts/options    |    5 -
 .../hosts/carol/etc/strongswan.conf                |   25 -
 .../tnc/tnccs-20-pt-tls/hosts/dave/etc/pts/options |    6 -
 .../tnccs-20-pt-tls/hosts/dave/etc/strongswan.conf |   22 -
 testing/tests/tnc/tnccs-20-pt-tls/posttest.dat     |    8 -
 testing/tests/tnc/tnccs-20-pt-tls/pretest.dat      |   19 -
 .../tests/tnc/tnccs-20-pts-no-ecc/description.txt  |   15 +-
 testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat |    4 +-
 .../hosts/carol/etc/strongswan.conf                |    8 +-
 .../hosts/dave/etc/strongswan.conf                 |    7 +-
 .../hosts/moon/etc/pts/data1.sql                   |    2 +-
 .../hosts/moon/etc/strongswan.conf                 |    7 +-
 testing/tests/tnc/tnccs-20-pts/description.txt     |   13 +-
 testing/tests/tnc/tnccs-20-pts/evaltest.dat        |   16 +-
 .../tnccs-20-pts/hosts/carol/etc/strongswan.conf   |    8 +-
 .../tnccs-20-pts/hosts/dave/etc/strongswan.conf    |    6 +-
 .../tnc/tnccs-20-pts/hosts/moon/etc/pts/data1.sql  |    2 +-
 .../tnccs-20-pts/hosts/moon/etc/strongswan.conf    |    7 +-
 .../tnc/tnccs-20-pts/hosts/moon/etc/tnc_config     |    1 -
 .../tnc/tnccs-20-server-retry/description.txt      |    9 +-
 .../hosts/carol/etc/strongswan.conf                |    8 +-
 .../hosts/dave/etc/strongswan.conf                 |    7 +-
 .../hosts/moon/etc/strongswan.conf                 |    7 +-
 testing/tests/tnc/tnccs-20-tls/description.txt     |    9 +-
 .../tnccs-20-tls/hosts/carol/etc/strongswan.conf   |    8 +-
 .../tnccs-20-tls/hosts/dave/etc/strongswan.conf    |    8 +-
 .../tnccs-20-tls/hosts/moon/etc/strongswan.conf    |   17 +-
 .../tnc/tnccs-20/hosts/carol/etc/strongswan.conf   |    8 +-
 .../tnc/tnccs-20/hosts/dave/etc/strongswan.conf    |    7 +-
 .../tnc/tnccs-20/hosts/moon/etc/strongswan.conf    |    7 +-
 testing/tests/tnc/tnccs-dynamic/description.txt    |    1 +
 .../tnccs-dynamic/hosts/carol/etc/strongswan.conf  |    5 +
 .../tnccs-dynamic/hosts/dave/etc/strongswan.conf   |    5 +
 .../tnccs-dynamic/hosts/moon/etc/strongswan.conf   |    1 +
 1302 files changed, 74032 insertions(+), 22840 deletions(-)

diff --git a/Android.common.mk b/Android.common.mk
index 9f49831..490f810 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.1.3"
+strongswan_VERSION := "5.2.0"
 
diff --git a/Android.mk b/Android.mk
index 6ad220b..7b8bc8f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -60,6 +60,7 @@ strongswan_CFLAGS := \
 	-DHAVE_ALLOCA_H \
 	-DHAVE_ALLOCA \
 	-DHAVE_CLOCK_GETTIME \
+	-DHAVE_DLADDR \
 	-DHAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC \
 	-DHAVE_PRCTL \
 	-DHAVE_LINUX_UDP_H \
diff --git a/Doxyfile.in b/Doxyfile.in
index af172e3..8adf83c 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -1,110 +1,121 @@
-# Doxyfile 1.8.1.2
+# Doxyfile 1.8.6
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project.
 #
-# All text after a hash (#) is considered a comment and will be ignored.
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
 # The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ").
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
 
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
 
 # This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
 
 DOXYFILE_ENCODING      = UTF-8
 
-# The PROJECT_NAME tag is a single word (or sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
 
 PROJECT_NAME           = "@PACKAGE_NAME@"
 
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
 
 PROJECT_NUMBER         = "@PACKAGE_VERSION@"
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer
-# a quick idea about the purpose of the project. Keep the description short.
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
 
 PROJECT_BRIEF          =
 
-# With the PROJECT_LOGO tag one can specify an logo or icon that is
-# included in the documentation. The maximum height of the logo should not
-# exceed 55 pixels and the maximum width should not exceed 200 pixels.
-# Doxygen will copy the logo to the output directory.
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
 
 PROJECT_LOGO           =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
 
 OUTPUT_DIRECTORY       = apidoc
 
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
 
 CREATE_SUBDIRS         = NO
 
 # The OUTPUT_LANGUAGE tag is used to specify the language in which all
 # documentation generated by doxygen is written. Doxygen will use this
 # information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
 
 OUTPUT_LANGUAGE        = English
 
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
 
 BRIEF_MEMBER_DESC      = YES
 
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
 # brief descriptions will be completely suppressed.
+# The default value is: YES.
 
 REPEAT_BRIEF           = YES
 
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
 
 ABBREVIATE_BRIEF       =
 
 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
+# doxygen will generate a detailed section even if there is only a brief
 # description.
+# The default value is: NO.
 
 ALWAYS_DETAILED_SEC    = NO
 
@@ -112,169 +123,204 @@ ALWAYS_DETAILED_SEC    = NO
 # inherited members of a class in the documentation of that class as if those
 # members were ordinary class members. Constructors, destructors and assignment
 # operators of the base classes will not be shown.
+# The default value is: NO.
 
 INLINE_INHERITED_MEMB  = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
 
 FULL_PATH_NAMES        = YES
 
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
 
 STRIP_FROM_PATH        =
 
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
 
 STRIP_FROM_INC_PATH    =
 
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
 
 SHORT_NAMES            = NO
 
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
 
 JAVADOC_AUTOBRIEF      = YES
 
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
 
 QT_AUTOBRIEF           = NO
 
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
 
 MULTILINE_CPP_IS_BRIEF = NO
 
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
 
 INHERIT_DOCS           = YES
 
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
 
 SEPARATE_MEMBER_PAGES  = NO
 
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
 
 TAB_SIZE               = 4
 
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
 
 ALIASES                =
 
 # This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding
-# "class=itcl::class" will allow you to use the command class in the
-# itcl::class meaning.
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
 
 TCL_SUBST              =
 
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
 
 OPTIMIZE_OUTPUT_JAVA   = NO
 
 # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
 
 OPTIMIZE_FOR_FORTRAN   = NO
 
 # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
 
 OPTIMIZE_OUTPUT_VHDL   = NO
 
 # Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this
-# tag. The format is ext=language, where ext is a file extension, and language
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
 # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
 
 EXTENSION_MAPPING      =
 
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
-# comments according to the Markdown format, which allows for more readable
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
 # documentation. See http://daringfireball.net/projects/markdown/ for details.
-# The output of markdown processing is further processed by doxygen, so you
-# can mix doxygen, HTML, and XML commands with Markdown formatting.
-# Disable only in case of backward compatibilities issues.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
 
 MARKDOWN_SUPPORT       = YES
 
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
 # diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
 
 BUILTIN_STL_SUPPORT    = NO
 
 # If you use Microsoft's C++/CLI language, you should set this option to YES to
 # enable parsing support.
+# The default value is: NO.
 
 CPP_CLI_SUPPORT        = NO
 
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
 
 SIP_SUPPORT            = NO
 
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
 
 IDL_PROPERTY_SUPPORT   = YES
 
@@ -282,67 +328,61 @@ IDL_PROPERTY_SUPPORT   = YES
 # tag is set to YES, then doxygen will reuse the documentation of the first
 # member in the group (if any) for the other members of the group. By default
 # all members of a group must be documented explicitly.
+# The default value is: NO.
 
 DISTRIBUTE_GROUP_DOC   = NO
 
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
 
 SUBGROUPING            = YES
 
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
-# unions are shown inside the group in which they are included (e.g. using
-# @ingroup) instead of on a separate page (for HTML and Man pages) or
-# section (for LaTeX and RTF).
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
 
 INLINE_GROUPED_CLASSES = NO
 
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields will be shown inline in the documentation
-# of the scope in which they are defined (i.e. file, namespace, or group
-# documentation), provided this scope is documented. If set to NO (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
 
 INLINE_SIMPLE_STRUCTS  = NO
 
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
 # typedef struct TypeS {} TypeT, will appear in the documentation as a struct
 # with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
 # types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
 
 TYPEDEF_HIDES_STRUCT   = YES
 
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penalty.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will roughly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-SYMBOL_CACHE_SIZE      = 0
-
-# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
-# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
-# their name and scope. Since this can be an expensive process and often the
-# same symbol appear multiple times in the code, doxygen keeps a cache of
-# pre-resolved symbols. If the cache is too small doxygen will become slower.
-# If the cache is too large, memory is wasted. The cache size is given by this
-# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
 
 LOOKUP_CACHE_SIZE      = 0
 
@@ -351,339 +391,390 @@ LOOKUP_CACHE_SIZE      = 0
 #---------------------------------------------------------------------------
 
 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
 
 EXTRACT_ALL            = NO
 
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
 
 EXTRACT_PRIVATE        = NO
 
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
 
 EXTRACT_PACKAGE        = NO
 
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
 
 EXTRACT_STATIC         = NO
 
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
 
 EXTRACT_LOCAL_CLASSES  = NO
 
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
 
 EXTRACT_LOCAL_METHODS  = NO
 
 # If this flag is set to YES, the members of anonymous namespaces will be
 # extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespaces are hidden.
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
 
 EXTRACT_ANON_NSPACES   = NO
 
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
 
 HIDE_UNDOC_MEMBERS     = NO
 
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
 
 HIDE_UNDOC_CLASSES     = NO
 
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
 
 HIDE_FRIEND_COMPOUNDS  = NO
 
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
 
 HIDE_IN_BODY_DOCS      = NO
 
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
 
 INTERNAL_DOCS          = NO
 
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
 # allowed. This is useful if you have classes or files whose names only differ
 # in case and if your file system supports case sensitive file names. Windows
 # and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
 
 CASE_SENSE_NAMES       = YES
 
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
 
 HIDE_SCOPE_NAMES       = NO
 
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
 
 SHOW_INCLUDE_FILES     = NO
 
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
 
 FORCE_LOCAL_INCLUDES   = NO
 
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
 
 INLINE_INFO            = YES
 
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
 
 SORT_MEMBER_DOCS       = NO
 
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
 
 SORT_BRIEF_DOCS        = NO
 
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
 
 SORT_MEMBERS_CTORS_1ST = NO
 
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
 
 SORT_GROUP_NAMES       = YES
 
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
 # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
 
 SORT_BY_SCOPE_NAME     = NO
 
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
-# do proper type resolution of all parameters of a function it will reject a
-# match between the prototype and the implementation of a member function even
-# if there is only one candidate or it is obvious which candidate to choose
-# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
-# will still accept a match between prototype and implementation in such cases.
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
 
 STRICT_PROTO_MATCHING  = NO
 
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
 
 GENERATE_TODOLIST      = NO
 
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
 
 GENERATE_TESTLIST      = NO
 
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
 
 GENERATE_BUGLIST       = NO
 
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
 
 GENERATE_DEPRECATEDLIST= NO
 
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
 
 ENABLED_SECTIONS       =
 
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or macro consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
 
 MAX_INITIALIZER_LINES  = 30
 
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
 
 SHOW_USED_FILES        = NO
 
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
 
 SHOW_FILES             = YES
 
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page.
-# This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
 
 SHOW_NAMESPACES        = YES
 
 # The FILE_VERSION_FILTER tag can be used to specify a program or script that
 # doxygen should invoke to get the current version for each file (typically from
 # the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
 
 FILE_VERSION_FILTER    =
 
 # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
 # by doxygen. The layout file controls the global structure of the generated
 # output files in an output format independent way. To create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
 
 LAYOUT_FILE            =
 
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
-# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path.
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
 
 CITE_BIB_FILES         =
 
 #---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
+# Configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
 
 QUIET                  = NO
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
 
 WARNINGS               = YES
 
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
 
 WARN_IF_UNDOCUMENTED   = NO
 
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
 
 WARN_IF_DOC_ERROR      = YES
 
-# The WARN_NO_PARAMDOC option can be enabled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
 
 WARN_NO_PARAMDOC       = YES
 
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
 
 WARN_FORMAT            = "$file:$line: $text"
 
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
 
 WARN_LOGFILE           =
 
 #---------------------------------------------------------------------------
-# configuration options related to the input files
+# Configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
 
-INPUT                  = @SRC_DIR@/src/
+INPUT                  = @SRC_DIR@/
 
 # This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
 
 INPUT_ENCODING         = UTF-8
 
 # If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
 
-FILE_PATTERNS          = *.h
+FILE_PATTERNS          = *.h *.md
 
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
 
 RECURSIVE              = YES
 
 # The EXCLUDE tag can be used to specify files and/or directories that should be
 # excluded from the INPUT source files. This way you can easily exclude a
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
@@ -692,14 +783,16 @@ EXCLUDE                = @SRC_DIR@/src/include
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
 # from the input.
+# The default value is: NO.
 
 EXCLUDE_SYMLINKS       = YES
 
 # If the value of the INPUT tag contains directories, you can use the
 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
 
 EXCLUDE_PATTERNS       = */.git/*
 
@@ -708,755 +801,1080 @@ EXCLUDE_PATTERNS       = */.git/*
 # output. The symbol name can be a fully qualified name, a word, or if the
 # wildcard * is used, a substring. Examples: ANamespace, AClass,
 # AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
 
 EXCLUDE_SYMBOLS        =
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
 
 EXAMPLE_PATH           =
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
 
 EXAMPLE_PATTERNS       =
 
 # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
 
 EXAMPLE_RECURSIVE      = NO
 
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
 
 IMAGE_PATH             =
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
 # invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
 
 INPUT_FILTER           =
 
 # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis.
-# Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match.
-# The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
 
 FILTER_PATTERNS        =
 
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
 
 FILTER_SOURCE_FILES    = NO
 
 # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
-# and it is also possible to disable source filtering for a specific pattern
-# using *.ext= (so without naming a filter). This option only has effect when
-# FILTER_SOURCE_FILES is enabled.
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
 
 FILTER_SOURCE_PATTERNS =
 
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
 #---------------------------------------------------------------------------
-# configuration options related to source browsing
+# Configuration options related to source browsing
 #---------------------------------------------------------------------------
 
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
 
 SOURCE_BROWSER         = YES
 
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
 
 INLINE_SOURCES         = NO
 
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C, C++ and Fortran comments will always remain visible.
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
 
 STRIP_CODE_COMMENTS    = NO
 
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
 
 REFERENCED_BY_RELATION = NO
 
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
 
 REFERENCES_RELATION    = NO
 
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.
-# Otherwise they will link to the documentation.
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
 
 REFERENCES_LINK_SOURCE = YES
 
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
 
 USE_HTAGS              = NO
 
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
 
 VERBATIM_HEADERS       = YES
 
 #---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
+# Configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
 
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
 
 ALPHABETICAL_INDEX     = YES
 
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
 COLS_IN_ALPHA_INDEX    = 5
 
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
 IGNORE_PREFIX          =
 
 #---------------------------------------------------------------------------
-# configuration options related to the HTML output
+# Configuration options related to the HTML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
 
 GENERATE_HTML          = YES
 
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_OUTPUT            = .
 
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_FILE_EXTENSION    = .html
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-#  for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_HEADER            =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_FOOTER            =
 
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# style sheet in the HTML output directory as well, or it will be erased!
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_STYLESHEET        =
 
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
 # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
 # other source files which should be copied to the HTML output directory. Note
 # that these files will be copied to the base HTML output directory. Use the
-# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that
-# the files will be copied as-is; there are no commands or markers available.
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_EXTRA_FILES       =
 
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the style sheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_COLORSTYLE_HUE    = 220
 
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_COLORSTYLE_SAT    = 100
 
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_COLORSTYLE_GAMMA  = 80
 
 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_TIMESTAMP         = YES
 
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # documentation will contain sections that can be hidden and shown after the
 # page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_DYNAMIC_SECTIONS  = YES
 
-# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
-# entries shown in the various tree structured indices initially; the user
-# can expand and collapse entries dynamically later on. Doxygen will expand
-# the tree to such a level that at most the specified number of entries are
-# visible (unless a fully collapsed tree already exceeds this amount).
-# So setting the number of entries 1 will produce a full collapsed tree by
-# default. 0 is a special value representing an infinite number of entries
-# and will result in a full expanded tree by default.
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_INDEX_NUM_ENTRIES = 100
 
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
 # for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_DOCSET        = NO
 
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_FEEDNAME        = "Doxygen generated docs"
 
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_BUNDLE_ID       = org.doxygen.Project
 
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
 # the documentation publisher. This should be a reverse domain-name style
 # string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
 
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
 
 DOCSET_PUBLISHER_NAME  = Publisher
 
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_HTMLHELP      = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
 # written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 CHM_FILE               =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 HHC_LOCATION           =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 GENERATE_CHI           = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 CHM_INDEX_ENCODING     =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 BINARY_TOC             = NO
 
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 TOC_EXPAND             = NO
 
 # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_QHP           = NO
 
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QCH_FILE               =
 
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_NAMESPACE          = org.doxygen.Project
 
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_VIRTUAL_FOLDER     = doc
 
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_NAME   =
 
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_ATTRS  =
 
 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_SECT_FILTER_ATTRS  =
 
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHG_LOCATION           =
 
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-#  will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_ECLIPSEHELP   = NO
 
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
 
 ECLIPSE_DOC_ID         = org.doxygen.Project
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 DISABLE_INDEX          = NO
 
 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_TREEVIEW      = YES
 
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 ENUM_VALUES_PER_LINE   = 1
 
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 TREEVIEW_WIDTH         = 250
 
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 EXT_LINKS_IN_WINDOW    = NO
 
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 FORMULA_FONTSIZE       = 10
 
 # Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 FORMULA_TRANSPARENT    = YES
 
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered bitmaps. Use this if you do not
-# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you may also need to install MathJax separately and
-# configure the path to it using the MATHJAX_RELPATH option.
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 USE_MATHJAX            = NO
 
-# When MathJax is enabled you need to specify the location relative to the
-# HTML output directory using the MATHJAX_RELPATH option. The destination
-# directory should contain the MathJax.js script. For instance, if the mathjax
-# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to
-# the MathJax Content Delivery Network so you can quickly see the result without
-# installing MathJax.
-# However, it is strongly recommended to install a local
-# copy of MathJax from http://www.mathjax.org before deployment.
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
 
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_EXTENSIONS     =
 
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 SEARCHENGINE           = NO
 
 # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvantages are that it is more difficult to setup
-# and does not have live searching capabilities.
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
 
 SERVER_BASED_SEARCH    = NO
 
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
 #---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
+# Configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
 
 GENERATE_LATEX         = NO
 
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_OUTPUT           = latex
 
 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_CMD_NAME         = latex
 
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 COMPACT_LATEX          = NO
 
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4wide will be used.
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 PAPER_TYPE             = a4wide
 
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 EXTRA_PACKAGES         =
 
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_HEADER           =
 
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
-# the generated latex document. The footer should contain everything after
-# the last chapter. If it is left blank doxygen will generate a
-# standard footer. Notice: only use this tag if you know what you are doing!
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_FOOTER           =
 
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 PDF_HYPERLINKS         = NO
 
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
 # higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 USE_PDFLATEX           = NO
 
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_BATCHMODE        = NO
 
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_HIDE_INDICES     = NO
 
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_SOURCE_CODE      = NO
 
 # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_BIB_STYLE        = plain
 
 #---------------------------------------------------------------------------
-# configuration options related to the RTF output
+# Configuration options related to the RTF output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
 
 GENERATE_RTF           = NO
 
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_OUTPUT             = rtf
 
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 COMPACT_RTF            = NO
 
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_HYPERLINKS         = NO
 
-# Load style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_STYLESHEET_FILE    =
 
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_EXTENSIONS_FILE    =
 
 #---------------------------------------------------------------------------
-# configuration options related to the man page output
+# Configuration options related to the man page output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
 
 GENERATE_MAN           = NO
 
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
 
 MAN_OUTPUT             = man
 
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
 
 MAN_EXTENSION          = .3
 
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
 
 MAN_LINKS              = YES
 
 #---------------------------------------------------------------------------
-# configuration options related to the XML output
+# Configuration options related to the XML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
 
 GENERATE_XML           = NO
 
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_OUTPUT             = xml
 
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_SCHEMA             =
 
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_DTD                =
 
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
 
 XML_PROGRAMLISTING     = YES
 
 #---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
 
 GENERATE_AUTOGEN_DEF   = NO
 
 #---------------------------------------------------------------------------
-# configuration options related to the Perl module output
+# Configuration options related to the Perl module output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
 
 GENERATE_PERLMOD       = NO
 
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
 PERLMOD_LATEX          = NO
 
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.
-# This is useful
-# if you want to understand what is going on.
-# On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
 PERLMOD_PRETTY         = YES
 
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
 PERLMOD_MAKEVAR_PREFIX =
 
@@ -1464,106 +1882,129 @@ PERLMOD_MAKEVAR_PREFIX =
 # Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
 
 ENABLE_PREPROCESSING   = YES
 
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 MACRO_EXPANSION        = YES
 
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 EXPAND_ONLY_PREDEF     = NO
 
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 SEARCH_INCLUDES        = YES
 
 # The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
 INCLUDE_PATH           =
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 INCLUDE_FILE_PATTERNS  =
 
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-PREDEFINED             = LEAK_DETECTIVE __attribute__(x)=
+PREDEFINED             = LEAK_DETECTIVE \
+                         __attribute__(x)=
 
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition that
-# overrules the definition found in the source code.
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 EXPAND_AS_DEFINED      =
 
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all references to function-like macros
-# that are alone on a line, have an all uppercase name, and do not end with a
-# semicolon, because these will confuse the parser if not removed.
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
 SKIP_FUNCTION_MACROS   = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to external references
+# Configuration options related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles. For each
-# tag file the location of the external documentation should be added. The
-# format of a tag file without this location is as follows:
-#
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
 # TAGFILES = file1 file2 ...
 # Adding location for the tag files is done as follows:
-#
 # TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths
-# or URLs. Note that each tag file must have a unique name (where the name does
-# NOT include the path). If a tag file is not located in the directory in which
-# doxygen is run, you must also specify the path to the tagfile here.
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
 
 TAGFILES               =
 
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
 
 GENERATE_TAGFILE       =
 
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
 
 ALLEXTERNALS           = NO
 
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
 
 EXTERNAL_GROUPS        = YES
 
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
 # The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
 
 PERL_PATH              = /usr/bin/perl
 
@@ -1571,222 +2012,293 @@ PERL_PATH              = /usr/bin/perl
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option also works with HAVE_DOT disabled, but it is recommended to
-# install and use dot, since it yields more powerful graphs.
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
 
 CLASS_DIAGRAMS         = YES
 
 # You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
 # documentation. The MSCGEN_PATH tag allows you to specify the directory where
 # the mscgen tool resides. If left empty the tool is assumed to be found in the
 # default search path.
 
 MSCGEN_PATH            =
 
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
 
 HIDE_UNDOC_RELATIONS   = YES
 
 # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
 
 HAVE_DOT               = NO
 
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_NUM_THREADS        = 0
 
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font you can specify
-# the font name using DOT_FONTNAME. You need to make sure dot is able to find
-# the font, which can be done by putting it in a standard location or by setting
-# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
-# directory containing the font.
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_FONTNAME           = FreeSans
+DOT_FONTNAME           =
 
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_FONTSIZE           = 10
 
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_FONTPATH           =
 
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 CLASS_GRAPH            = YES
 
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 COLLABORATION_GRAPH    = YES
 
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 GROUP_GRAPHS           = YES
 
 # If the UML_LOOK tag is set to YES doxygen will generate inheritance and
 # collaboration diagrams in a style similar to the OMG's Unified Modeling
 # Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 UML_LOOK               = NO
 
-# If the UML_LOOK tag is enabled, the fields and methods are shown inside
-# the class node. If there are many fields or methods and many nodes the
-# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
-# threshold limits the number of items for each type to make the size more
-# managable. Set this to 0 for no limit. Note that the threshold may be
-# exceeded by 50% before the limit is enforced.
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 UML_LIMIT_NUM_FIELDS   = 10
 
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 TEMPLATE_RELATIONS     = NO
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 INCLUDE_GRAPH          = YES
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 INCLUDED_BY_GRAPH      = YES
 
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 CALL_GRAPH             = NO
 
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 CALLER_GRAPH           = NO
 
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 GRAPHICAL_HIERARCHY    = YES
 
-# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DIRECTORY_GRAPH        = YES
 
 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. If you choose svg you need to set
-# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible in IE 9+ (other browsers do not have this requirement).
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_IMAGE_FORMAT       = png
 
 # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
 # enable generation of interactive SVG images that allow zooming and panning.
-# Note that this requires a modern browser other than Internet Explorer.
-# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
-# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible. Older versions of IE do not have SVG support.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 INTERACTIVE_SVG        = NO
 
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
 # found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_PATH               =
 
 # The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOTFILE_DIRS           =
 
 # The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the
-# \mscfile command).
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
 
 MSCFILE_DIRS           =
 
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_GRAPH_MAX_NODES    = 50
 
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
 # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_TRANSPARENT        = NO
 
 # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
 # files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_MULTI_TARGETS      = NO
 
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 GENERATE_LEGEND        = YES
 
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_CLEANUP            = YES
diff --git a/Makefile.am b/Makefile.am
index 7e3c72b..0703abc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -55,7 +55,7 @@ cov-report:
 		lcov -r $(top_builddir)/coverage/coverage.info '*/tests/*' \
 			 -o $(top_builddir)/coverage/coverage.cleaned.info \
 			 --rc lcov_branch_coverage=1
-		genhtml --num-spaces 4 --legend --branch-coverage \
+		genhtml --num-spaces 4 --legend --branch-coverage --ignore-errors source \
 				-t "$(PACKAGE_STRING)" \
 				-o $(top_builddir)/coverage/html \
 				-p `readlink -m $(abs_top_srcdir)`/src \
diff --git a/Makefile.in b/Makefile.in
index 7115717..e8c0ff5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -294,6 +294,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -312,6 +313,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -339,6 +341,7 @@ 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@
@@ -430,6 +433,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -492,8 +496,8 @@ $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
 $(am__aclocal_m4_deps):
 
 config.h: stamp-h1
-	@if test ! -f $@; then rm -f stamp-h1; else :; fi
-	@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
+	@test -f $@ || rm -f stamp-h1
+	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
 
 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
 	@rm -f stamp-h1
@@ -725,10 +729,16 @@ dist-xz: distdir
 	$(am__post_remove_distdir)
 
 dist-tarZ: distdir
+	@echo WARNING: "Support for shar distribution archives is" \
+	               "deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
 	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
 	$(am__post_remove_distdir)
 
 dist-shar: distdir
+	@echo WARNING: "Support for distribution archives compressed with" \
+		       "legacy program 'compress' is deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
 	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
 	$(am__post_remove_distdir)
 
@@ -770,9 +780,10 @@ distcheck: dist
 	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
 	  && am__cwd=`pwd` \
 	  && $(am__cd) $(distdir)/_build \
-	  && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+	  && ../configure \
 	    $(AM_DISTCHECK_CONFIGURE_FLAGS) \
 	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	    --srcdir=.. --prefix="$$dc_install_base" \
 	  && $(MAKE) $(AM_MAKEFLAGS) \
 	  && $(MAKE) $(AM_MAKEFLAGS) dvi \
 	  && $(MAKE) $(AM_MAKEFLAGS) check \
@@ -992,7 +1003,7 @@ cov-reset-common:
 @COVERAGE_TRUE@		lcov -r $(top_builddir)/coverage/coverage.info '*/tests/*' \
 @COVERAGE_TRUE@			 -o $(top_builddir)/coverage/coverage.cleaned.info \
 @COVERAGE_TRUE@			 --rc lcov_branch_coverage=1
- at COVERAGE_TRUE@		genhtml --num-spaces 4 --legend --branch-coverage \
+ at COVERAGE_TRUE@		genhtml --num-spaces 4 --legend --branch-coverage --ignore-errors source \
 @COVERAGE_TRUE@				-t "$(PACKAGE_STRING)" \
 @COVERAGE_TRUE@				-o $(top_builddir)/coverage/html \
 @COVERAGE_TRUE@				-p `readlink -m $(abs_top_srcdir)`/src \
diff --git a/NEWS b/NEWS
index fd33fb0..cebeeba 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,51 @@
+strongswan-5.2.0
+----------------
+
+- strongSwan has been ported to the Windows platform. Using a MinGW toolchain,
+  many parts of the strongSwan codebase run natively on Windows 7 / 2008 R2
+  and newer releases. charon-svc implements a Windows IKE service based on
+  libcharon, the kernel-iph and kernel-wfp plugins act as networking and IPsec
+  backend on the Windows platform. socket-win provides a native IKE socket
+  implementation, while winhttp fetches CRL and OCSP information using the
+  WinHTTP API.
+
+- The new vici plugin provides a Versatile IKE Configuration Interface for
+  charon. Using the stable IPC interface, external applications can configure,
+  control and monitor the IKE daemon. Instead of scripting the ipsec tool
+  and generating ipsec.conf, third party applications can use the new interface
+  for more control and better reliability.
+
+- Built upon the libvici client library, swanctl implements the first user of
+  the VICI interface. Together with a swanctl.conf configuration file,
+  connections can be defined, loaded and managed. swanctl provides a portable,
+  complete IKE configuration and control interface for the command line.
+  The first six swanctl example scenarios have been added.
+
+- The SWID IMV implements a JSON-based REST API which allows the exchange
+  of SWID tags and Software IDs with the strongTNC policy manager.
+
+- The SWID IMC can extract all installed packages from the dpkg (Debian,
+  Ubuntu, Linux Mint etc.), rpm (Fedora, RedHat, OpenSUSE, etc.), or
+  pacman (Arch Linux, Manjaro, etc.) package managers, respectively, using the
+  swidGenerator (https://github.com/strongswan/swidGenerator) which generates
+  SWID tags according to the new ISO/IEC 19770-2:2014 standard.
+
+- All IMVs now share the access requestor ID, device ID and product info
+  of an access requestor via a common imv_session object.
+
+- The Attestation IMC/IMV pair supports the IMA-NG measurement format
+  introduced with the Linux 3.13 kernel.
+
+- The aikgen tool generates an Attestation Identity Key bound to a TPM.
+
+- Implemented the PT-EAP transport protocol (RFC 7171) for Trusted Network
+  Connect.
+
+- The ipsec.conf replay_window option defines connection specific IPsec replay
+  windows. Original patch courtesy of Zheng Zhong and Christophe Gouault from
+  6Wind.
+
+
 strongswan-5.1.3
 ----------------
 
diff --git a/README b/README
index aa40fe3..e344424 100644
--- a/README
+++ b/README
@@ -1,82 +1,35 @@
-                 ----------------------------
-                  strongSwan - Configuration
-                 ----------------------------
-
-
-Contents
---------
-
-   1. Overview
-   2. Quickstart
-    2.1 Site-to-Site case
-    2.2 Host-to-Host case
-    2.3 Roadwarrior case
-    2.4 Roadwarrior case with virtual IP
-   3. Generating X.509 certificates and CRLs
-    3.1 Generating a CA certificate
-    3.2 Generating a host or user certificate
-    3.3 Generating a CRL
-    3.4 Revoking a certificate
-   4. Configuring the connections - ipsec.conf
-    4.1 Configuring my side
-    4.2 Multiple certificates
-    4.3 Configuring the peer side using CA certificates
-    4.4 Handling Virtual IPs and wildcard subnets
-    4.5 Protocol and port selectors
-    4.6 IPsec policies based on wildcards
-    4.7 IPsec policies based on CA certificates
-   5. Configuring certificates and CRLs
-    5.1 Installing CA certificates
-    5.2 Installing optional Certificate Revocation Lists (CRLs)
-    5.3 Dynamic update of certificates and CRLs
-    5.4 Local caching of CRLs
-    5.5 Online Certificate Status Protocol (OCSP)
-    5.6 CRL policy
-    5.7 Configuring the peer side using locally stored certificates
-   6. Configuring the private keys - ipsec.secrets
-    6.1 Loading private key files in PKCS#1 format
-    6.2 Entering passphrases interactively
-    6.3 Multiple private keys
-   7. Configuring CA properties - ipsec.conf
-   8. Monitoring functions
-   9. Firewall support functions
-       9.1 Environment variables in the updown script
-       9.2 Automatic insertion and deletion of iptables firewall rules
-
-
-1. Overview
-   --------
-
-strongSwan is an OpenSource IPsec solution for Unix based operating systems.
+# strongSwan Configuration #
+
+## Overview ##
+
+strongSwan is an OpenSource IPsec-based VPN solution.
 
 This document is just a short introduction, for more detailed information
-consult the manual pages and our wiki:
+consult the man pages and [**our wiki**](http://wiki.strongswan.org).
 
-    http://wiki.strongswan.org
 
+## Quickstart ##
 
-2. Quickstart
-   ----------
+In the following examples we assume, for reasons of clarity, that **left**
+designates the **local** host and that **right** is the **remote** host.
 
-In the following examples we assume for reasons of clarity that left designates
-the local host and that right is the remote host.  Certificates for users,
-hosts and gateways are issued by a fictitious strongSwan CA.  How to generate
-private keys and certificates using OpenSSL or the strongSwan PKI tool will be
-explained in section 3.  The CA certificate "strongswanCert.pem" must be present
-on all VPN end points in order to be able to authenticate the peers.
+Certificates for users, hosts and gateways are issued by a fictitious
+strongSwan CA.  How to generate private keys and certificates using OpenSSL or
+the strongSwan PKI tool will be explained in one of the sections below.
+The CA certificate `strongswanCert.pem` must be present on all VPN endpoints
+in order to be able to authenticate the peers.
 
 
-2.1 Site-to-site case
-    -----------------
+### Site-to-site case ###
 
-In this scenario two security gateways moon and sun will connect the
-two subnets moon-net and sun-net with each other through a VPN tunnel
+In this scenario two security gateways _moon_ and _sun_ will connect the
+two subnets _moon-net_ and _sun-net_ with each other through a VPN tunnel
 set up between the two gateways:
 
     10.1.0.0/16 -- | 192.168.0.1 | === | 192.168.0.2 | -- 10.2.0.0/16
       moon-net          moon                 sun           sun-net
 
-Configuration on gateway moon:
+Configuration on gateway _moon_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -96,7 +49,7 @@ Configuration on gateway moon:
             rightid="C=CH, O=strongSwan, CN=sun.strongswan.org"
             auto=start
 
-Configuration on gateway sun:
+Configuration on gateway _sun_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -117,8 +70,7 @@ Configuration on gateway sun:
             auto=start
 
 
-2.2 Host-to-host case
-    -----------------
+### Host-to-host case ###
 
 This is a setup between two single hosts which don't have a subnet behind
 them.  Although IPsec transport mode would be sufficient for host-to-host
@@ -127,7 +79,7 @@ connections we will use the default IPsec tunnel mode.
     | 192.168.0.1 | === | 192.168.0.2 |
          moon                sun
 
-Configuration on host moon:
+Configuration on host _moon_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -145,7 +97,7 @@ Configuration on host moon:
             rightid="C=CH, O=strongSwan, CN=sun.strongswan.org"
             auto=start
 
-Configuration on host sun:
+Configuration on host _sun_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -164,8 +116,7 @@ Configuration on host sun:
             auto=start
 
 
-2.3 Roadwarrior case
-    ----------------
+### Roadwarrior case ###
 
 This is a very common case where a strongSwan gateway serves an arbitrary
 number of remote VPN clients usually having dynamic IP addresses.
@@ -173,7 +124,7 @@ number of remote VPN clients usually having dynamic IP addresses.
     10.1.0.0/16 -- | 192.168.0.1 | === | x.x.x.x |
       moon-net          moon              carol
 
-Configuration on gateway moon:
+Configuration on gateway _moon_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -191,7 +142,7 @@ Configuration on gateway moon:
             right=%any
             auto=add
 
-Configuration on roadwarrior carol:
+Configuration on roadwarrior _carol_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -211,29 +162,28 @@ Configuration on roadwarrior carol:
             auto=start
 
 
-2.6 Roadwarrior case with virtual IP
-    --------------------------------
+### Roadwarrior case with virtual IP ###
 
 Roadwarriors usually have dynamic IP addresses assigned by the ISP they are
-currently attached to.  In order to simplify the routing from moon-net back
-to the remote access client carol it would be desirable if the roadwarrior had
-an inner IP address chosen from a pre-assigned pool.
+currently attached to.  In order to simplify the routing from _moon-net_ back
+to the remote access client _carol_ it would be desirable if the roadwarrior had
+an inner IP address chosen from a pre-defined pool.
 
     10.1.0.0/16 -- | 192.168.0.1 | === | x.x.x.x | -- 10.3.0.1
       moon-net          moon              carol       virtual IP
 
 In our example the virtual IP address is chosen from the address pool
-10.3.0.0/16 which can be configured by adding the parameter
+`10.3.0.0/16` which can be configured by adding the parameter
 
     rightsourceip=10.3.0.0/16
 
-to the gateway's ipsec.conf.  To request an IP address from this pool a
+to the gateway's `ipsec.conf`.  To request an IP address from this pool a
 roadwarrior can use IKEv1 mode config or IKEv2 configuration payloads.
 The configuration for both is the same
 
     leftsourceip=%config
 
-Configuration on gateway moon:
+Configuration on gateway _moon_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -252,7 +202,7 @@ Configuration on gateway moon:
             rightsourceip=10.3.0.0/16
             auto=add
 
-Configuration on roadwarrior carol:
+Configuration on roadwarrior _carol_:
 
     /etc/ipsec.d/cacerts/strongswanCert.pem
 
@@ -273,29 +223,28 @@ Configuration on roadwarrior carol:
             auto=start
 
 
-3. Generating certificates and CRLs
-   --------------------------------
+## Generating certificates and CRLs ##
 
 This section is not a full-blown tutorial on how to use OpenSSL or the
 strongSwan PKI tool.  It just lists a few points that are relevant if you want
 to generate your own certificates and CRLs for use with strongSwan.
 
 
-3.1 Generating a CA certificate
-    ---------------------------
+### Generating a CA certificate ###
 
 The OpenSSL statement
 
     openssl req -x509 -days 1460 -newkey rsa:4096 \
                 -keyout strongswanKey.pem -out strongswanCert.pem
 
-creates a 4096 bit RSA private key strongswanKey.pem and a self-signed CA
-certificate strongswanCert.pem with a validity of 4 years (1460 days).
+creates a 4096 bit RSA private key `strongswanKey.pem` and a self-signed CA
+certificate `strongswanCert.pem` with a validity of 4 years (1460 days).
 
     openssl x509 -in cert.pem -noout -text
 
-lists the properties of  a X.509 certificate cert.pem. It allows you to verify
-whether the configuration defaults in openssl.cnf have been inserted correctly.
+lists the properties of  a X.509 certificate `cert.pem`. It allows you to verify
+whether the configuration defaults in `openssl.cnf` have been inserted
+correctly.
 
 If you prefer the CA certificate to be in binary DER format then the following
 command achieves this transformation:
@@ -311,28 +260,27 @@ The statements
     ipsec pki --print --in strongswanCert.der
 
 achieve about the same with the strongSwan PKI tool.  Unlike OpenSSL the tool
-stores keys and certificates in the binary DER format by default.  The --outform
-option may be used to write PEM encoded files.
+stores keys and certificates in the binary DER format by default.
+The `--outform` option may be used to write PEM encoded files.
 
-The directory /etc/ipsec.d/cacerts contains all required CA certificates either
-in binary DER or in base64 PEM format, irrespective of the file suffix the
-correct format will be determined.
+The directory `/etc/ipsec.d/cacerts` contains all required CA certificates
+either in binary DER or in Base64 PEM format, irrespective of the file suffix
+the correct format will be determined.
 
 
-3.2 Generating a host or user certificate
-    -------------------------------------
+### Generating a host or user certificate ###
 
 The OpenSSL statement
 
      openssl req -newkey rsa:2048 -keyout hostKey.pem \
                  -out hostReq.pem
 
-generates a 2048 bit RSA private key hostKey.pem and a certificate request
-hostReq.pem which has to be signed by the CA.
+generates a 2048 bit RSA private key `hostKey.pem` and a certificate request
+`hostReq.pem` which has to be signed by the CA.
 
-If you want to add a subjectAltName field to the host certificate you must edit
-the OpenSSL configuration file openssl.cnf and add the following line in the
-[ usr_cert ] section:
+If you want to add a _subjectAltName_ field to the host certificate you must
+edit the OpenSSL configuration file `openssl.cnf` and add the following line in
+the `[ usr_cert ]` section:
 
      subjectAltName=DNS:moon.strongswan.org
 
@@ -340,7 +288,7 @@ if you want to identify the host by its Fully Qualified Domain Name (FQDN), or
 
      subjectAltName=IP:192.168.0.1
 
-if you want the ID to be of type IPV4_ADDR. Of course you could include both
+if you want the ID to be of type _IPV4_ADDR_. Of course you could include both
 ID types with
 
      subjectAltName=DNS:moon.strongswan.org,IP:192.168.0.1
@@ -348,7 +296,7 @@ ID types with
 but the use of an IP address for the identification of a host should be
 discouraged anyway.
 
-For user certificates the appropriate ID type is RFC822_ADDR which can be
+For user certificates the appropriate ID type is _RFC822_ADDR_ which can be
 specified as
 
      subjectAltName=email:carol at strongswan.org
@@ -361,15 +309,15 @@ Now the certificate request can be signed by the CA with the command
 
      openssl ca -in hostReq.pem -days 730 -out hostCert.pem -notext
 
-If you omit the -days option then the default_days value (365 days) specified
-in openssl.cnf is used.  The -notext option avoids that a human readable
-listing of the certificate is prepended to the base64 encoded certificate
-body.
+If you omit the `-days` option then the `default_days` value (365 days)
+specified in `openssl.cnf` is used.  The `-notext` option avoids that a human
+readable listing of the certificate is prepended to the Base64 encoded
+certificate body.
 
-If you want to use the dynamic CRL fetching feature described in section 4.7
-then you may include one or several crlDistributionPoints in your end
-certificates.  This can be done in the [ usr_cert ] section of the openssl.cnf
-configuration file:
+If you want to use the dynamic CRL fetching feature described in one of the
+following sections then you may include one or several _crlDistributionPoints_
+in your end certificates.  This can be done in the `[ usr_cert ]` section of the
+`openssl.cnf` configuration file:
 
     crlDistributionPoints=@crl_dp
 
@@ -394,11 +342,11 @@ Again the statements
               --san moon.strongswan.org --san 192.168.0.1 \
               --crl http://crl.strongswan.org/strongswan.crl > moonCert.der
 
-do something thing similar using the strongSwan PKI tool.
+do something similar using the strongSwan PKI tool.
 
 Usually, a Windows or Mac OS X (or iOS) based VPN client needs its private key,
-its host or user certificate, and the CA certificate. The most convenient way
-to load this information is to put everything into a PKCS#12 file:
+its host or user certificate, and the CA certificate.  The most convenient way
+to load this information is to put everything into a PKCS#12 container:
 
      openssl pkcs12 -export -inkey carolKey.pem \
                     -in carolCert.pem -name "carol" \
@@ -406,32 +354,30 @@ to load this information is to put everything into a PKCS#12 file:
                     -out carolCert.p12
 
 
-3.3 Generating a CRL
-    ----------------
+### Generating a CRL ###
 
 An empty CRL that is signed by the CA can be generated with the command
 
      openssl ca -gencrl -crldays 15 -out crl.pem
 
-If you omit the -crldays option then the default_crl_days value (30 days)
-specified in openssl.cnf is used.
+If you omit the `-crldays` option then the `default_crl_days` value (30 days)
+specified in `openssl.cnf` is used.
 
 If you prefer the CRL to be in binary DER format then this conversion
 can be achieved with
 
      openssl crl -in crl.pem -outform DER -out cert.crl
 
-The strongSwan PKI tool provides the ipsec pki --signcrl command to sign CRLs.
+The strongSwan PKI tool provides the `--signcrl` command to sign CRLs.
 
-The directory /etc/ipsec.d/crls contains all CRLs either in binary DER
-or in base64 PEM format, irrespective of the file suffix the correct format
+The directory `/etc/ipsec.d/crls` contains all CRLs either in binary DER
+or in Base64 PEM format, irrespective of the file suffix the correct format
 will be determined.
 
 
-3.4 Revoking a certificate
-    ----------------------
+### Revoking a certificate ###
 
-A specific host certificate stored in the file host.pem is revoked with the
+A specific host certificate stored in the file `host.pem` is revoked with the
 command
 
      openssl ca -revoke host.pem
@@ -444,30 +390,28 @@ The content of the CRL file can be listed with the command
 
      openssl crl -in crl.pem -noout -text
 
-in the case of a base64 CRL, or alternatively for a CRL in DER format
+in the case of a Base64 CRL, or alternatively for a CRL in DER format
 
      openssl crl -inform DER -in cert.crl -noout -text
 
-Again the ipsec pki --signcrl command may be used to create new CRLs containing
-additional certificates.
+Again the `--signcrl` command of the strongSwan PKI tool may also be used to
+create new CRLs containing additional certificates.
 
 
-4. Configuring the connections - ipsec.conf
-   ----------------------------------------
+## Configuring the connections - ipsec.conf ##
 
-4.1 Configuring my side
-    -------------------
+### Configuring my side ###
 
-Usually the local side is the same for all connections.  Therefore it makes
+Usually the **local** side is the same for all connections.  Therefore it makes
 sense to put the definitions characterizing the strongSwan security gateway into
-the conn %default section of the configuration file /etc/ipsec.conf.  If we
-assume throughout this document that the strongSwan security gateway is left and
-the peer is right then we can write
+the `conn %default` section of the configuration file `/etc/ipsec.conf`.  If we
+assume throughout this document that the strongSwan security gateway is **left**
+and the peer is **right** then we can write
 
-conn %default
-     leftcert=moonCert.pem
-     # load connection definitions automatically
-     auto=add
+    conn %default
+         leftcert=moonCert.pem
+         # load connection definitions automatically
+         auto=add
 
 The X.509 certificate by which the strongSwan security gateway will authenticate
 itself by sending it in binary form to its peers as part of the Internet Key
@@ -475,23 +419,16 @@ Exchange (IKE) is specified in the line
 
      leftcert=moonCert.pem
 
-The certificate can either be stored in base64 PEM-format or in the binary
+The certificate can either be stored in Base64 PEM-format or in the binary
 DER-format. Irrespective of the file suffix the correct format will be
-determined.  Therefore
-
-     leftcert=moonCert.der
-
-or
-
-     leftcert=moonCert.cer
-
+determined.  Therefore `leftcert=moonCert.der` or `leftcert=moonCert.cer`
 would also be valid alternatives.
 
 When using relative pathnames as in the examples above, the certificate files
-must be stored in in the directory /etc/ipsec.d/certs.  In order to distinguish
-strongSwan's own certificates from locally stored trusted peer certificates
-(see section 5.5 for details), they could also be stored in a subdirectory
-below /etc/ipsec.d/certs as e.g. in
+must be stored in in the directory `/etc/ipsec.d/certs`.  In order to
+distinguish strongSwan's own certificates from locally stored trusted peer
+certificates (see below for details), they could also be stored in a
+subdirectory below `/etc/ipsec.d/certs` as e.g. in
 
     leftcert=mycerts/moonCert.pem
 
@@ -502,173 +439,142 @@ Absolute pathnames are also possible as in
 As an ID for the VPN gateway we recommend the use of a Fully Qualified Domain
 Name (FQDN) of the form
 
-conn rw
-     right=%any
-     leftid=@moon.strongswan.org
+    conn rw
+         right=%any
+         leftid=moon.strongswan.org
 
-Important: When a FQDN identifier is used it must be explicitly included as a
-so called subjectAltName of type dnsName (DNS:) in the certificate indicated
-by leftcert.  For details on how to generate certificates with subjectAltNames,
-please refer to section 3.2.
+**Important**: When a FQDN identifier is used it must be explicitly included as
+a so called _subjectAltName_ of type _dnsName_ (`DNS:`) in the certificate
+indicated by `leftcert`.  For details on how to generate certificates with
+_subjectAltNames_, please refer to the sections above.
 
-If you don't want to mess with subjectAltNames, you can use the certificate's
-Distinguished Name (DN) instead, which is an identifier of type DER_ASN1_DN
+If you don't want to mess with _subjectAltNames_, you can use the certificate's
+Distinguished Name (DN) instead, which is an identifier of type _DER_ASN1_DN_
 and which can be written e.g. in the LDAP-type format
 
-conn rw
-     right=%any
-     leftid="C=CH, O=strongSwan, CN=moon.strongswan.org"
+    conn rw
+         right=%any
+         leftid="C=CH, O=strongSwan, CN=moon.strongswan.org"
 
-Since the subject's DN is part of the certificate, the leftid does not have to
+Since the subject's DN is part of the certificate, the `leftid` does not have to
 be declared explicitly. Thus the entry
 
-conn rw
-     right=%any
+    conn rw
+         right=%any
 
-automatically assumes the subject DN of leftcert to be the host ID.
+automatically assumes the subject DN of `leftcert` to be the host ID.
 
 
-4.2 Multiple certificates
-    ---------------------
+### Multiple certificates ###
 
 strongSwan supports multiple local host certificates and corresponding
 RSA private keys:
 
-conn rw1
-     right=%any
-     rightid=@peer1.domain1
-     leftcert=myCert1.pem
-     # leftid is DN of myCert1
+    conn rw1
+         right=%any
+         rightid=peer1.domain1
+         leftcert=myCert1.pem
+         # leftid is DN of myCert1
 
-conn rw2
-     right=%any
-     rightid=@peer2.domain2
-     leftcert=myCert2.pem
-     # leftid is DN of myCert2
+    conn rw2
+         right=%any
+         rightid=peer2.domain2
+         leftcert=myCert2.pem
+         # leftid is DN of myCert2
 
-When peer1 initiates a connection then strongSwan will send myCert1 and will
-sign with myKey1 defined in /etc/ipsec.secrets (see section 6.2) whereas
-myCert2 and myKey2 will be used in a connection setup started from peer2.
+When _peer1_ initiates a connection then strongSwan will send _myCert1_ and will
+sign with _myKey1_ defined in `/etc/ipsec.secrets` (see below) whereas
+_myCert2_ and _myKey2_ will be used in a connection setup started from _peer2_.
 
 
-4.3 Configuring the peer side using CA certificates
-    -----------------------------------------------
+### Configuring the peer side using CA certificates ###
 
 Now we can proceed to define our connections.  In many applications we might
 have dozens of road warriors connecting to a central strongSwan security
 gateway. The following most simple statement:
 
-conn rw
-     right=%any
+    conn rw
+         right=%any
 
-defines the general roadwarrior case.  The line right=%any literally means that
-any IPsec peer is accepted, regardless of its current IP source address and its
-ID, as long as the peer presents a valid X.509 certificate signed by a CA the
-strongSwan security gateway puts explicit trust in.  Additionally, the signature
-during IKE gives proof that the peer is in possession of the private RSA key
-matching the public key contained in the transmitted certificate.
+defines the general roadwarrior case.  The line `right=%any` literally means
+that any IPsec peer is accepted, regardless of its current IP source address and
+its ID, as long as the peer presents a valid X.509 certificate signed by a CA
+the strongSwan security gateway puts explicit trust in.  Additionally, the
+signature during IKE gives proof that the peer is in possession of the private
+key matching the public key contained in the transmitted certificate.
 
 The ID by which a peer is identifying itself during IKE can by any of the ID
-types IPV[46]_ADDR, FQDN, RFC822_ADDR or DER_ASN1_DN.  If one of the first
-three ID types is used, then the accompanying X.509 certificate of the peer
-must contain a matching subjectAltName field of the type ipAddress (IP:),
-dnsName (DNS:) or rfc822Name (email:), respectively.  With the fourth type
-DER_ASN1_DN the identifier must completely match the subject field of the
-peer's certificate.  One of the two possible representations of a
+types _IPV[46]_ADDR_, _FQDN_, _RFC822_ADDR_ or _DER_ASN1_DN_.  If one of the
+first three ID types is used, then the accompanying X.509 certificate of the
+peer must contain a matching _subjectAltName_ field of the type _ipAddress_
+(`IP:`), _dnsName_ (`DNS:`) or _rfc822Name_ (`email:`), respectively.  With the
+fourth type, _DER_ASN1_DN_, the identifier must completely match the subject
+field of the peer's certificate.  One of the two possible representations of a
 Distinguished Name (DN) is the LDAP-type format
 
      rightid="C=CH, O=strongSwan IPsec, CN=sun.strongswan.org"
 
 Additional whitespace can be added everywhere as desired since it will be
-automatically eliminated by the X.509 parser.  An exception is the single
-whitespace between individual words, like e.g. in strongSwan IPsec, which is
-preserved by the parser.
+automatically eliminated by the parser.  An exception is the single whitespace
+between individual words, like e.g. in `strongSwan IPsec`, which is preserved.
 
 The Relative Distinguished Names (RDNs) can alternatively be separated by a
-slash '/' instead of a comma ','
+slash `/` instead of a comma `,`
 
      rightid="/C=CH/O=strongSwan IPsec/CN=sun.strongswan.org"
 
 This is the representation extracted from the certificate by the OpenSSL
-command line option
+`-subject` command line option
 
      openssl x509 -in sunCert.pem -noout -subject
 
 The following RDNs are supported by strongSwan
 
-+-------------------------------------------------------+
-| DC                   Domain Component                 |
-|-------------------------------------------------------|
-| C                    Country                          |
-|-------------------------------------------------------|
-| ST                   State or province                |
-|-------------------------------------------------------|
-| L                    Locality or town                 |
-|-------------------------------------------------------|
-| O                    Organization                     |
-|-------------------------------------------------------|
-| OU                   Organizational Unit              |
-|-------------------------------------------------------|
-| CN                   Common Name                      |
-|-------------------------------------------------------|
-| ND                   NameDistinguisher, used with CN  |
-|-------------------------------------------------------|
-| N                    Name                             |
-|-------------------------------------------------------|
-| G                    Given name                       |
-|-------------------------------------------------------|
-| S                    Surname                          |
-|-------------------------------------------------------|
-| I                    Initials                         |
-|-------------------------------------------------------|
-| T                    Personal title                   |
-|-------------------------------------------------------|
-| E                    E-mail                           |
-|-------------------------------------------------------|
-| Email                E-mail                           |
-|-------------------------------------------------------|
-| emailAddress         E-mail                           |
-|-------------------------------------------------------|
-| SN                   Serial number                    |
-|-------------------------------------------------------|
-| serialNumber         Serial number                    |
-|-------------------------------------------------------|
-| D                    Description                      |
-|-------------------------------------------------------|
-| ID                   X.500 Unique Identifier          |
-|-------------------------------------------------------|
-| UID                  User ID                          |
-|-------------------------------------------------------|
-| TCGID                [Siemens] Trust Center Global ID |
-|-------------------------------------------------------|
-| UN                   Unstructured Name                |
-|-------------------------------------------------------|
-| unstructuredName     Unstructured Name                |
-|-------------------------------------------------------|
-| UA                   Unstructured Address             |
-|-------------------------------------------------------|
-| unstructuredAddress  Unstructured Address             |
-|-------------------------------------------------------|
-| EN                   Employee Number                  |
-|-------------------------------------------------------|
-| employeeNumber       Employee Number                  |
-|-------------------------------------------------------|
-| dnQualifier          DN Qualifier                     |
-+-------------------------------------------------------+
+| Name               | Description                      |
+|--------------------|----------------------------------|
+| DC                 | Domain Component                 |
+| C                  | Country                          |
+| ST                 | State or province                |
+| L                  | Locality or town                 |
+| O                  | Organization                     |
+| OU                 | Organizational Unit              |
+| CN                 | Common Name                      |
+| ND                 | NameDistinguisher, used with CN  |
+| N                  | Name                             |
+| G                  | Given name                       |
+| S                  | Surname                          |
+| I                  | Initials                         |
+| T                  | Personal title                   |
+| E                  | E-mail                           |
+| Email              | E-mail                           |
+| emailAddress       | E-mail                           |
+| SN                 | Serial number                    |
+| serialNumber       | Serial number                    |
+| D                  | Description                      |
+| ID                 | X.500 Unique Identifier          |
+| UID                | User ID                          |
+| TCGID              | [Siemens] Trust Center Global ID |
+| UN                 | Unstructured Name                |
+| unstructuredName   | Unstructured Name                |
+| UA                 | Unstructured Address             |
+| unstructuredAddress| Unstructured Address             |
+| EN                 | Employee Number                  |
+| employeeNumber     | Employee Number                  |
+| dnQualifier        | DN Qualifier                     |
 
 With the roadwarrior connection definition listed above, an IPsec SA for
-the strongSwan security gateway moon.strongswan.org itself can be established.
-If any roadwarrior should be able to reach e.g. the two subnets 10.1.0.0/24
-and 10.1.3.0/24 behind the security gateway then the following connection
+the strongSwan security gateway `moon.strongswan.org` itself can be established.
+If the roadwarriors should be able to reach e.g. the two subnets `10.1.0.0/24`
+and `10.1.3.0/24` behind the security gateway then the following connection
 definitions will make this possible
 
-conn rw1
-     right=%any
-     leftsubnet=10.1.0.0/24
+    conn rw1
+         right=%any
+         leftsubnet=10.1.0.0/24
 
-conn rw3
-     right=%any
-     leftsubnet=10.1.3.0/24
+    conn rw3
+         right=%any
+         leftsubnet=10.1.3.0/24
 
 For IKEv2 connections this can even be simplified by using
 
@@ -677,199 +583,192 @@ For IKEv2 connections this can even be simplified by using
 If not all peers in possession of a X.509 certificate signed by a specific
 certificate authority shall be given access to the Linux security gateway,
 then either a subset of them can be barred by listing the serial numbers of
-their certificates in a certificate revocation list (CRL) as specified in
-section 5.2 or as an alternative, access can be controlled by explicitly
-putting a roadwarrior entry for each eligible peer into ipsec.conf:
+their certificates in a certificate revocation list (CRL) or as an alternative,
+access can be controlled by explicitly putting a roadwarrior entry for each
+eligible peer into `ipsec.conf`:
 
-conn sun
-     right=%any
-     rightid=@sun.strongswan.org
+    conn sun
+         right=%any
+         rightid=sun.strongswan.org
 
-conn carol
-     right=%any
-     rightid=carol at strongswan.org
+    conn carol
+         right=%any
+         rightid=carol at strongswan.org
 
-conn dave
-     right=%any
-     rightid="C=CH, O=strongSwan, CN=dave at strongswan.org"
+    conn dave
+         right=%any
+         rightid="C=CH, O=strongSwan, CN=dave at strongswan.org"
 
 When the IP address of a peer is known to be stable, it can be specified as
 well.  This entry is mandatory when the strongSwan host wants to act as the
 initiator of an IPsec connection.
 
-conn sun
-     right=192.168.0.2
-     rightid=@sun.strongswan.org
+    conn sun
+         right=192.168.0.2
+         rightid=sun.strongswan.org
 
-conn carol
-     right=192.168.0.100
-     rightid=carol at strongswan.org
+    conn carol
+         right=192.168.0.100
+         rightid=carol at strongswan.org
 
-conn dave
-     right=192.168.0.200
-     rightid="C=CH, O=strongSwan, CN=dave at strongswan.org"
+    conn dave
+         right=192.168.0.200
+         rightid="C=CH, O=strongSwan, CN=dave at strongswan.org"
 
-conn venus
-     right=192.168.0.50
+    conn venus
+         right=192.168.0.50
 
-In the last example the ID types FQDN, RFC822_ADDR, DER_ASN1_DN and IPV4_ADDR,
-respectively, were used.  Of course all connection definitions presented so far
-have included the lines in the conn %defaults section, comprising among other
-a leftcert entry.
+In the last example the ID types _FQDN_, _RFC822_ADDR_, _DER_ASN1_DN_ and
+_IPV4_ADDR_, respectively, were used.  Of course all connection definitions
+presented so far have included the lines in the `conn %defaults` section,
+comprising among other a `leftcert` entry.
 
 
-4.4 Handling Virtual IPs and narrowing
-    ----------------------------------
+### Handling Virtual IPs and narrowing ###
 
-Often roadwarriors are behind NAT-boxes with IPsec passthrough, which causes
-the inner IP source address of an IPsec tunnel to be different from the
-outer IP source address usually assigned dynamically by the ISP.
-Whereas the varying outer IP address can be handled by the right=%any
-construct, the inner IP address or subnet must always be declared in a
-connection definition. Therefore for the three roadwarriors rw1 to rw3
-connecting to a strongSwan security gateway the following entries are
-required in /etc/ipsec.conf:
+Often roadwarriors are behind NAT-boxes, which causes the inner IP source
+address of an IPsec tunnel to be different from the outer IP source address
+usually assigned dynamically by the ISP.  Whereas the varying outer IP address
+can be handled by the `right=%any` construct, the inner IP address or subnet
+must always be declared in a connection definition. Therefore for the three
+roadwarriors _rw1_ to _rw3_ connecting to a strongSwan security gateway the
+following entries are required in `/etc/ipsec.conf`:
 
-conn rw1
-     right=%any
-     righsubnet=10.4.0.5/32
+    conn rw1
+         right=%any
+         righsubnet=10.4.0.5/32
 
-conn rw2
-     right=%any
-     rightsubnet=10.4.0.47/32
+    conn rw2
+         right=%any
+         rightsubnet=10.4.0.47/32
 
-conn rw3
-     right=%any
-     rightsubnet=10.4.0.128/28
+    conn rw3
+         right=%any
+         rightsubnet=10.4.0.128/28
 
 Because the charon daemon uses narrowing (even for IKEv1) these three entries
 can be reduced to the single connection definition
 
-conn rw
-     right=%any
-     rightsubnet=10.4.0.0/24
+    conn rw
+         right=%any
+         rightsubnet=10.4.0.0/24
 
 Any host will be accepted (of course after successful authentication based on
 the peer's X.509 certificate only) if it declares a client subnet lying totally
-within the brackets defined by the subnet definition (in our example
-10.4.0.0/24).
+within the boundaries defined by the subnet definition (in our example
+`10.4.0.0/24`).
 
 This strongSwan feature can also be helpful with VPN clients getting a
 dynamically assigned inner IP from a DHCP server located on the NAT router box.
 
+Since the private IP address of roadwarriors will often not be known they are
+usually assigned virtual IPs from a predefined pool.  This also makes routing
+traffic back to the roadwarriors easier. For example, to assign each client an
+IP address from the `10.5.0.0/24` subnet `conn rw` can be defined as
 
-4.5 Protocol and Port Selectors
-    ---------------------------
+    conn rw
+         right=%any
+         rightsourceip=10.5.0.0/24
 
-strongSwan offer the possibility to restrict the protocol and optionally the
-ports in an IPsec SA using the rightprotoport and leftprotoport parameters.
 
-Some examples:
+### Protocol and Port Selectors ###
 
-conn icmp
-     right=%any
-     rightprotoport=icmp
-     leftid=@moon.strongswan.org
-     leftprotoport=icmp
-
-conn http
-     right=%any
-     rightprotoport=6
-     leftid=@moon.strongswan.org
-     leftprotoport=6/80
-
-conn l2tp       # with port wildcard for Mac OS X Panther interoperability
-     right=%any
-     rightprotoport=17/%any
-     leftid=@moon.strongswan.org
-     leftprotoport=17/1701
-
-conn dhcp
-     right=%any
-     rightprotoport=udp/bootpc
-     leftid=@moon.strongswan.org
-     leftsubnet=0.0.0.0/0  #allows DHCP discovery broadcast
-     leftprotoport=udp/bootps
-     rekey=no
-     keylife=20s
-     rekeymargin=10s
-     auto=add
+strongSwan offers the possibility to restrict the protocol and optionally the
+ports in an IPsec SA using the `rightprotoport` and `leftprotoport` parameters.
+For IKEv2 multiple such restrictions can also be configured in
+`leftsubnet` and `rightsubnet`.
 
-Protocols and ports can be designated either by their numerical values
-or by their acronyms defined in /etc/services.
-
-    ipsec status
+Some examples:
 
-shows the following connection definitions:
+    conn icmp
+         right=%any
+         rightprotoport=icmp
+         leftid=moon.strongswan.org
+         leftprotoport=icmp
+
+    conn http
+         right=%any
+         rightprotoport=6
+         leftid=moon.strongswan.org
+         leftprotoport=6/80
+
+    conn l2tp
+         right=%any
+         # with port wildcard for interoperability with certain L2TP clients
+         rightprotoport=17/%any
+         leftid=moon.strongswan.org
+         leftprotoport=17/1701
+
+    conn dhcp
+         right=%any
+         rightprotoport=udp/bootpc
+         leftid=moon.strongswan.org
+         leftsubnet=0.0.0.0/0  #allows DHCP discovery broadcast
+         leftprotoport=udp/bootps
 
-"icmp": 192.168.0.1[@moon.strongswan.org]:1/0...%any:1/0
-"http": 192.168.0.1[@moon.strongswan.org]:6/80...%any:6/0
-"l2tp": 192.168.0.1[@moon.strongswan.org]:17/1701...%any:17/%any
-"dhcp": 0.0.0.0/0===192.168.0.1[@moon.strongswan.org]:17/67...%any:17/68
+Protocols and ports can be designated either by their numerical values
+or by their acronyms defined in `/etc/services`.
 
 Based on the protocol and port selectors appropriate policies will be set
 up, so that only the specified payload types will pass through the IPsec
 tunnel.
 
 
-4.6 IPsec policies based on wildcards
-    ---------------------------------
+### IPsec policies based on wildcards ###
 
 In large VPN-based remote access networks there is often a requirement that
 access to the various parts of an internal network must be granted selectively,
 e.g. depending on the group membership of the remote access user.  strongSwan
 makes this possible by applying wildcard filtering on the VPN user's
-distinguished name (ID_DER_ASN1_DN).
+distinguished name (_ID_DER_ASN1_DN_).
 
 Let's make a practical example:
 
-An organization has a sales department (OU=Sales) and a research group
-(OU=Research).  In the company intranet there are separate subnets for Sales
-(10.0.0.0/24) and Research (10.0.1.0/24) but both groups share a common web
-server (10.0.2.100).  The VPN clients use Virtual IP addresses that are either
+An organization has a sales department (_OU=Sales_) and a research group
+(_OU=Research_).  In the company intranet there are separate subnets for Sales
+(`10.0.0.0/24`) and Research (`10.0.1.0/24`) but both groups share a common web
+server (`10.0.2.100`).  The VPN clients use Virtual IP addresses that are either
 assigned statically or from a dynamic pool.  The sales and research departments
-use IP addresses from separate address pools (10.1.0.0/24) and (10.1.1.0/24),
-respectively.  An X.509 certificate is issued to each employee, containing in
-its subject distinguished name the country (C=CH), the company (O=ACME),
-the group membership(OU=Sales or OU=Research) and the common name (e.g.
-CN=Bart Simpson).
+use IP addresses from separate address pools (`10.1.0.0/24`) and
+(`10.1.1.0/24`), respectively.  An X.509 certificate is issued to each employee,
+containing in its subject distinguished name the country (_C=CH_), the company
+(_O=ACME_), the group membership (_OU=Sales_ or _OU=Research_) and the common
+name (e.g. _CN=Bart Simpson_).
 
 The IPsec policy defined above can now be enforced with the following three
 IPsec security associations:
 
-conn sales
-     right=%any
-     rightid="C=CH, O=ACME, OU=Sales, CN=*"
-     rightsubnet=10.1.0.0/24         # Sales IP range
-     leftsubnet=10.0.0.0/24          # Sales subnet
-
-conn research
-     right=%any
-     rightid="C=CH, O=ACME, OU=Research, CN=*"
-     rightsubnet=10.1.1.0/24         # Research IP range
-     leftsubnet=10.0.1.0/24          # Research subnet
-
-conn web
-     right=%any
-     rightid="C=CH, O=ACME, OU=*, CN=*"
-     rightsubnet=10.1.0.0/23         # Remote access IP range
-     leftsubnet=10.0.2.100/32        # Web server
-     rightprotoport=tcp              # TCP protocol only
-     leftprotoport=tcp/http          # TCP port 80 only
-
-The '*' character is used as a wildcard in relative distinguished names (RDNs).
-In order to match a wildcard template, the ID_DER_ASN1_DN of a peer must contain
-the same number of RDNs (selected from the list in section 4.3) appearing in the
-exact order defined by the template.
+    conn sales
+         right=%any
+         rightid="C=CH, O=ACME, OU=Sales, CN=*"
+         rightsourceip=10.1.0.0/24       # Sales IP range
+         leftsubnet=10.0.0.0/24          # Sales subnet
+
+    conn research
+         right=%any
+         rightid="C=CH, O=ACME, OU=Research, CN=*"
+         rightsourceip=10.1.1.0/24       # Research IP range
+         leftsubnet=10.0.1.0/24          # Research subnet
+
+    conn web
+         right=%any
+         rightid="C=CH, O=ACME, OU=*, CN=*"
+         rightsubnet=10.1.0.0/23         # Remote access IP range
+         leftsubnet=10.0.2.100/32        # Web server
+         rightprotoport=tcp              # TCP protocol only
+         leftprotoport=tcp/http          # TCP port 80 only
+
+The `*` character is used as a wildcard in relative distinguished names (RDNs).
+In order to match a wildcard template, the _ID_DER_ASN1_DN_ of a peer must
+contain the same number of RDNs (selected from the list given earlier) appearing
+in the exact order defined by the template.
 
     "C=CH, O=ACME, OU=Research, OU=Special Effects, CN=Bart Simpson"
 
 matches the templates
 
     "C=CH, O=ACME, OU=Research, OU=*, CN=*"
-
     "C=CH, O=ACME, OU=*, OU=Special Effects, CN=*"
-
     "C=CH, O=ACME, OU=*, OU=*, CN=*"
 
 but not the template
@@ -879,79 +778,74 @@ but not the template
 which doesn't have the same number of RDNs.
 
 
-4.7 IPsec policies based on CA certificates
-    ---------------------------------------
-
-As an alternative to the wildcard based IPsec policies described in section 4.6,
-access to specific client host and subnets can be controlled on the basis of
-the CA that issued the peer certificate
+### IPsec policies based on CA certificates ###
 
+As an alternative to the wildcard based IPsec policies described above, access
+to specific client host and subnets can be controlled on the basis of the CA
+that issued the peer certificate
 
-conn sales
-     right=%any
-     rightca="C=CH, O=ACME, OU=Sales, CN=Sales CA"
-     rightsubnet=10.1.0.0/24         # Sales IP range
-     leftsubnet=10.0.0.0/24          # Sales subnet
+    conn sales
+         right=%any
+         rightca="C=CH, O=ACME, OU=Sales, CN=Sales CA"
+         rightsourceip=10.1.0.0/24       # Sales IP range
+         leftsubnet=10.0.0.0/24          # Sales subnet
 
-conn research
-     right=%any
-     rightca="C=CH, O=ACME, OU=Research, CN=Research CA"
-     rightsubnet=10.1.1.0/24         # Research IP range
-     leftsubnet=10.0.1.0/24          # Research subnet
+    conn research
+         right=%any
+         rightca="C=CH, O=ACME, OU=Research, CN=Research CA"
+         rightsourceip=10.1.1.0/24       # Research IP range
+         leftsubnet=10.0.1.0/24          # Research subnet
 
-conn web
-     right=%any
-     rightca="C=CH, O=ACME, CN=ACME Root CA"
-     rightsubnet=10.1.0.0/23         # Remote access IP range
-     leftsubnet=10.0.2.100/32        # Web server
-     rightprotoport=tcp              # TCP protocol only
-     leftprotoport=tcp/http          # TCP port 80 only
+    conn web
+         right=%any
+         rightca="C=CH, O=ACME, CN=ACME Root CA"
+         rightsubnet=10.1.0.0/23         # Remote access IP range
+         leftsubnet=10.0.2.100/32        # Web server
+         rightprotoport=tcp              # TCP protocol only
+         leftprotoport=tcp/http          # TCP port 80 only
 
-In the example above, the connection "sales" can be used by peers
+In the example above, the connection _sales_ can be used by peers
 presenting certificates issued by the Sales CA, only.  In the same way,
-the use of the connection "research" is restricted to owners of certificates
-issued by the Research CA.  The connection "web" is open to both "Sales" and
-"Research" peers because the required "ACME Root CA" is the issuer of the
-Research and Sales intermediate CAs.  If no rightca parameter is present
+the use of the connection _research_ is restricted to owners of certificates
+issued by the Research CA.  The connection _web_ is open to both "Sales" and
+"Research" peers because the required _ACME Root CA_ is the issuer of the
+Research and Sales intermediate CAs.  If no `rightca` parameter is present
 then any valid certificate issued by one of the trusted CAs in
-/etc/ipsec.d/cacerts can be used by the peer.
+`/etc/ipsec.d/cacerts` can be used by the peer.
 
-The leftca parameter usually doesn't have to be set explicitly because
+The `leftca` parameter usually doesn't have to be set explicitly because
 by default it is set to the issuer field of the certificate loaded via
-leftcert.  The statement
+`leftcert`.  The statement
 
      rightca=%same
 
 sets the CA requested from the peer to the CA used by the left side itself
 as e.g. in
 
-conn sales
-     right=%any
-     rightca=%same
-     leftcert=mySalesCert.pem
+    conn sales
+         right=%any
+         rightca=%same
+         leftcert=mySalesCert.pem
 
 
-5. Configuring certificates and CRLs
-   ---------------------------------
+## Configuring certificates and CRLs ##
 
 
-5.1 Installing the CA certificates
-    ------------------------------
+### Installing the CA certificates ###
 
 X.509 certificates received by strongSwan during the IKE protocol are
 automatically authenticated by going up the trust chain until a self-signed
 root CA certificate is reached.  Usually host certificates are directly signed
 by a root CA, but strongSwan also supports multi-level hierarchies with
 intermediate CAs in between.  All CA certificates belonging to a trust chain
-must be copied in either binary DER or base64 PEM format into the directory
+must be copied in either binary DER or Base64 PEM format into the directory
 
      /etc/ipsec.d/cacerts/
 
 
-5.2 Installing optional certificate revocation lists (CRLs)
-    -------------------------------------------------------
+### Installing optional certificate revocation lists (CRLs) ###
 
-By copying a CA certificate into /etc/ipsec.d/cacerts/, automatically all user
+By copying a CA certificate into `/etc/ipsec.d/cacerts/`, automatically all user
 or host certificates issued by this CA are declared valid.  Unfortunately,
 private keys might get compromised inadvertently or intentionally, personal
 certificates of users leaving a company have to be blocked immediately, etc.
@@ -960,97 +854,85 @@ contain the serial numbers of all user or host certificates that have been
 revoked due to various reasons.
 
 After successful verification of the X.509 trust chain, strongSwan searches its
-list of CRLs either obtained by loading them from the /etc/ipsec.d/crls/
-directory or fetching them dynamically from a HTTP or LDAP server for the
+list of CRLs, either obtained by loading them from the `/etc/ipsec.d/crls/`
+directory, or fetching them dynamically from a HTTP or LDAP server, for the
 presence of a CRL issued by the CA that has signed the certificate.
 
 If the serial number of the certificate is found in the CRL then the public key
-contained in the certificate is declared invalid and the IPsec SA will not be
-established.  If no CRL is found or if the deadline defined in the nextUpdate
+contained in the certificate is declared invalid and the IKE SA will not be
+established.  If no CRL is found or if the deadline defined in the _nextUpdate_
 field of the CRL has been reached, a warning is issued but the public key will
-nevertheless be accepted.  CRLs must be stored either in binary DER or base64
-PEM format in the crls directory.
+nevertheless be accepted (this behavior can be changed, see below).  CRLs must
+be stored either in binary DER or Base64 PEM format in the `crls` directory.
 
 
-5.3 Dynamic update of certificates and CRLs
-    ---------------------------------------
+### Dynamic update of certificates and CRLs ###
 
 strongSwan reads certificates and CRLs from their respective files during system
 startup and keeps them in memory.  X.509 certificates have a finite life span
 defined by their validity field.  Therefore it must be possible to replace CA or
 OCSP certificates kept in system memory without disturbing established IKE SAs.
 Certificate revocation lists should also be updated in the regular intervals
-indicated by the nextUpdate field in the CRL body.  The following interactive
+indicated by the _nextUpdate_ field in the CRL body.  The following interactive
 commands allow the manual replacement of the various files:
 
-+---------------------------------------------------------------------------+
-| ipsec rereadsecrets       reload file /etc/ipsec.secrets                  |
-|---------------------------------------------------------------------------|
-| ipsec rereadcacerts       reload all files in /etc/ipsec.d/cacerts/       |
-|---------------------------------------------------------------------------|
-| ipsec rereadaacerts       reload all files in /etc/ipsec.d/aacerts/       |
-|---------------------------------------------------------------------------|
-| ipsec rereadocspcerts     reload all files in /etc/ipsec.d/ocspcerts/     |
-|---------------------------------------------------------------------------|
-| ipsec rereadacerts        reload all files in /etc/ipsec.d/acerts/        |
-|---------------------------------------------------------------------------|
-| ipsec rereadcrls          reload all files in /etc/ipsec.d/crls/          |
-|---------------------------------------------------------------------------|
-| ipsec rereadall           ipsec rereadsecrets                             |
-|                                 rereadcacerts                             |
-|                                 rereadaacerts                             |
-|                                 rereadocspcerts                           |
-|                                 rereadacerts                              |
-|                                 rereadcrls                                |
-|---------------------------------------------------------------------------|
-| ipsec purgeocsp           purge the OCSP cache and fetching requests      |
-+---------------------------------------------------------------------------+
+
+| Command                 | Action                                          |
+|-------------------------|-------------------------------------------------|
+| ipsec rereadaacerts     | reload all files in `/etc/ipsec.d/aacerts/`     |
+| ipsec rereadacerts      | reload all files in `/etc/ipsec.d/acerts/`      |
+| ipsec rereadcacerts     | reload all files in `/etc/ipsec.d/cacerts/`     |
+| ipsec rereadcrls        | reload all files in `/etc/ipsec.d/crls/`        |
+| ipsec rereadocspcerts   | reload all files in `/etc/ipsec.d/ocspcerts/`   |
+| ipsec rereadsecrets     | reload `/etc/ipsec.secrets` and configured keys |
+| ipsec rereadall         | all the commands above combined                 |
+| ipsec purgecerts        | purge all cached certificates                   |
+| ipsec purgecrl          | purge all cached CRLs                           |
+| ipsec purgeocsp         | purge the OCSP cache                            |
+
 
 CRLs can also be automatically fetched from an HTTP or LDAP server by using
 the CRL distribution points contained in X.509 certificates.
 
 
-5.4 Local caching of CRLs
-    ---------------------
+### Local caching of CRLs ###
 
-The the ipsec.conf option
+The `ipsec.conf` option
 
-   config setup
-        cachecrls=yes
+    config setup
+         cachecrls=yes
 
 activates the local caching of CRLs that were dynamically fetched from an
-HTTP or LDAP server.  Cached copies are stored in /etc/ipsec.d/crls using a
-unique filename formed from the issuer's SubjectKeyIdentifier and the
-suffix .crl.
+HTTP or LDAP server.  Cached copies are stored in `/etc/ipsec.d/crls` using a
+unique filename formed from the issuer's _subjectKeyIdentifier_ and the
+suffix `.crl`.
 
 With the cached copy the CRL is immediately available after startup.  When the
 local copy is about to expire it is automatically replaced with an updated CRL
 fetched from one of the defined CRL distribution points.
 
 
-5.5 Online Certificate Status Protocol (OCSP)
-    -----------------------------------------
+### Online Certificate Status Protocol (OCSP) ###
 
-The Online Certificate Status Protocol is defined by RFC 2560.  It can be
+The _Online Certificate Status Protocol_ is defined by RFC 2560.  It can be
 used to query an OCSP server about the current status of an X.509 certificate
 and is often used as a more dynamic alternative to a static Certificate
 Revocation List (CRL).  Both the OCSP request sent by the client and the OCSP
 response messages returned by the server are transported via a standard
-TCP/HTTP connection.  Therefore cURL support must be enabled during
-configuration.
+TCP/HTTP connection.
 
 In the simplest OCSP setup, a default URI under which the OCSP server for a
-given CA can be accessed is defined in ipsec.conf:
+given CA can be accessed is defined in `ipsec.conf`:
 
-   ca strongswan
-        cacert=strongswanCert.pem
-        ocspuri=http://ocsp.strongswan.org:8880
-        auto=add
+    ca strongswan
+         cacert=strongswanCert.pem
+         ocspuri=http://ocsp.strongswan.org:8880
+         auto=add
 
 The HTTP port can be freely chosen.
 
 OpenSSL implements an OCSP server that can be used in conjunction with an
-openssl-based Public Key Infrastructure.  The OCSP server is started with the
+OpenSSL-based Public Key Infrastructure.  The OCSP server is started with the
 following command:
 
     openssl ocsp -index index.txt -CA strongswanCert.pem -port 8880 \
@@ -1059,34 +941,35 @@ following command:
 
 The command consists of the parameters
 
- -index    index.txt is a copy of the OpenSSL index file containing the list of
-           all issued certificates.  The certificate status in index.txt
-           is designated either by V for valid or R for revoked.  If a new
-           certificate is added or if a certificate is revoked using the
-           openssl ca command, the OCSP server must be restarted in order for
-           the changes in index.txt to take effect.
+    -index   index.txt is a copy of the OpenSSL index file containing the list
+             of all issued certificates.  The certificate status in index.txt
+             is designated either by V for valid or R for revoked.  If a new
+             certificate is added or if a certificate is revoked using the
+             openssl ca command, the OCSP server must be restarted in order for
+             the changes in index.txt to take effect.
 
- -CA       the CA certificate
+    -CA      the CA certificate
 
- -port     the HTTP port the OCSP server is listening on.
+    -port    the HTTP port the OCSP server is listening on.
 
- -rkey     the private key used to sign the OCSP response.  The use of the
-           sensitive CA private key is not recommended since this could
-           jeopardize the security of your production PKI if the OCSP
-           server is hacked.  It is much better to generate a special
-           RSA private key just for OCSP signing use instead.
+    -rkey    the private key used to sign the OCSP response.  The use of the
+             sensitive CA private key is not recommended since this could
+             jeopardize the security of your production PKI if the OCSP
+             server is hacked.  It is much better to generate a special
+             RSA private key just for OCSP signing use instead.
 
- -rsigner  the certificate of the OCSP server containing a public key which
-           matches the private key defined by -rkey and which can be used by
-           the client to check the trustworthiness of the signed OCSP response.
+    -rsigner the certificate of the OCSP server containing a public key which
+             matches the private key defined by -rkey and which can be used by
+             the client to check the trustworthiness of the signed OCSP
+             response.
 
- -resp_no_certs  With this option the OCSP signer certificate defined by
-                 -rsigner is not included in the OCSP response.
+    -resp_no_certs  With this option the OCSP signer certificate defined by
+                    -rsigner is not included in the OCSP response.
 
- -nmin     the validity interval of an OCSP response given in minutes.
+    -nmin    the validity interval of an OCSP response given in minutes.
 
- -text     this option activates a verbose logging output, showing the contents
-           of both the received OCSP request and sent OCSP response.
+    -text    this option activates a verbose logging output, showing the
+             contents of both the received OCSP request and sent OCSP response.
 
 
 The OCSP signer certificate can either be put into the default directory
@@ -1100,91 +983,90 @@ must be included in the OCSP server certificate.  Just insert the parameter
 
     extendedKeyUsage=OCSPSigner
 
-in the [ usr_cert ] section of your openssl.cnf configuration file before
+in the `[ usr_cert ]` section of your `openssl.cnf` configuration file before
 the CA signs the OCSP server certificate.
 
-For a given CA the corresponding ca section in ipsec.conf (see section 7) allows
+For a given CA the corresponding _ca_ section in `ipsec.conf` (see below) allows
 to define the URI of a single OCSP server.  As an alternative an OCSP URI can be
 embedded into each host and user certificate by putting the line
 
     authorityInfoAccess = OCSP;URI:http://ocsp.strongswan.org:8880
 
-into the [ usr_cert ] section of your openssl.cnf configuration file.
-If an OCSP authorityInfoAccess extension is present in a certificate then this
+into the `[ usr_cert ]` section of your `openssl.cnf` configuration file.
+If an OCSP _authorityInfoAccess_ extension is present in a certificate then this
 record overrides the default URI defined by the ca section.
 
 
-5.6 CRL Policy
-    ----------
+### CRL Policy ###
 
 By default strongSwan is quite tolerant concerning the handling of CRLs. It is
-not mandatory for a CRL to be present in /etc/ipsec.d/crls and if the expiration
-date defined by the nextUpdate field of a CRL has been reached just a warning
-is issued but a peer certificate will always be accepted if it has not been
-revoked.
+not mandatory for a CRL to be present in `/etc/ipsec.d/crls` and if the
+expiration date defined by the _nextUpdate_ field of a CRL has been reached just
+a warning is issued but a peer certificate will always be accepted if it has not
+been revoked.
 
 If you want to enforce a stricter CRL policy then you can do this by setting
-the "strictcrlpolicy" option.  This is done in the "config setup" section
-of the ipsec.conf file:
+the `strictcrlpolicy` option.  This is done in the `config setup` section
+of the `ipsec.conf` file:
 
     config setup
          strictcrlpolicy=yes
           ...
 
 A certificate received from a peer will not be accepted if no corresponding
-CRL or OCSP response is available.  And if an ISAKMP SA re-negotiation takes
-place after the nextUpdate deadline has been reached, the peer certificate
-will be declared invalid and the cached RSA public key will be deleted, causing
+CRL or OCSP response is available.  And if an IKE SA re-negotiation takes
+place after the _nextUpdate_ deadline has been reached, the peer certificate
+will be declared invalid and the cached public key will be deleted, causing
 the connection in question to fail.  Therefore if you are going to use the
-"strictcrlpolicy=yes" option, make sure that the CRLs will always be updated
-in time.  Otherwise a total standstill would ensue.
+`strictcrlpolicy=yes` option, make sure that the CRLs will always be updated
+in time.  Otherwise a total standstill might ensue.
 
-As mentioned earlier the default setting is "strictcrlpolicy=no"
+As mentioned earlier the default setting is `strictcrlpolicy=no`.
 
 
-5.7 Configuring the peer side using locally stored certificates
-    -----------------------------------------------------------
+### Configuring the peer side using locally stored certificates ###
 
-If you don't want to use trust chains based on CA certificates as proposed in
-section 4.3 you can alternatively import trusted peer certificates directly.
-Thus you do not have to rely on the certificate to be transmitted by the peer
-as part of the IKE protocol.
+If you don't want to use trust chains based on CA certificates as proposed above
+you can alternatively import trusted peer certificates directly.
 
-With the conn %default section defined in section 4.1 and the use of the
-rightcert keyword for the peer side, the connection definitions in section 4.3
-can alternatively be written as
+With the `conn %default` section defined above and the use of the `rightcert`
+keyword for the peer side, the connection definitions presented earlier can
+alternatively be written as
 
     conn sun
           right=%any
-          rightid=@sun.strongswan.org
+          rightid=sun.strongswan.org
           rightcert=sunCert.cer
 
      conn carol
           right=192.168.0.100
           rightcert=carolCert.der
 
-If the peer certificates are loaded locally then there is no sense in sending
-any certificates to the other end via the IKE protocol.  Especially if
-self-signed certificates are used which wouldn't be accepted anyway by
-the other side.  In these cases it is recommended to add
+If the peer certificates are loaded locally then there is no need to send any
+certificates to the other end via the IKE protocol.  Especially if self-signed
+certificates are used which wouldn't be accepted anyway by the other side.
+In these cases it is recommended to add
 
     leftsendcert=never
 
-to the connection definition[s] in order to avoid the sending of the host's
+to the connection definition(s) in order to avoid the sending of the host's
 own certificate.  The default value is
 
     leftsendcert=ifasked
 
-If a peer does not send a certificate request then use the setting
+which causes certificates to only be sent if a certificate request is received.
+If a peer does not send a certificate request then the setting
 
     leftsendcert=always
 
-If a peer certificate contains a subjectAltName extension, then an alternative
-rightid type can be used, as the example "conn sun" shows.  If no rightid
+may be used to force sending of the certificate to the other peer.
+
+If a peer certificate contains a _subjectAltName_ extension, then an alternative
+`rightid` type can be used, as the example `conn sun` shows.  If no `rightid`
 entry is present then the subject distinguished name contained in the
 certificate is taken as the ID.
 
-Using the same rules concerning pathnames that apply to strongSwan's own
+Using the same rules concerning pathnames that apply to the gateway's own
 certificates, the following two definitions are also valid for trusted peer
 certificates:
 
@@ -1195,21 +1077,20 @@ or
     rightcert=/usr/ssl/certs/carolCert.der
 
 
-6. Configuring the private keys - ipsec.secrets
-   --------------------------------------------
+## Configuring the private keys - ipsec.secrets ##
+
 
-6.1 Loading private key files in PKCS#1 or PKCS#8 format
-    ----------------------------------------------------
+### Loading private key files ###
 
-Besides strongSwan's raw private key format strongSwan has been enabled to
-load RSA (or ECDSA) private keys in the PKCS#1 or PKCS#8 file format.
-The key files can be optionally secured with a passphrase.
+strongSwan is able to load RSA (or ECDSA) private keys in the PKCS#1 or PKCS#8
+file formats, or from PKCS#12 containers. The key files can optionally be
+secured with a passphrase.
 
-RSA private key files are declared in /etc/ipsec.secrets using the syntax
+RSA private key files are declared in `/etc/ipsec.secrets` using the syntax
 
     : RSA <my keyfile> "<optional passphrase>"
 
-The key file can be either in base64 PEM-format or binary DER-format.  The
+The key file can be either in Base64 PEM-format or binary DER-format.  The
 actual coding is detected automatically.  The example
 
     : RSA moonKey.pem
@@ -1231,44 +1112,37 @@ cipher using a transport key derived from a cryptographically strong
 passphrase.
 
 Once on the security gateway the private key can either be permanently
-unlocked so that it can be used by Pluto without having to know a
+unlocked so that it can be used by the IKE daemon without having to know a
 passphrase
 
     openssl rsa -in moonKey.pem -out moonKey.pem
 
 or as an option the key file can remain secured.  In this case the passphrase
 unlocking the private key must be added after the pathname in
-/etc/ipsec.secrets
+`/etc/ipsec.secrets`
 
     : RSA moonKey.pem "This is my passphrase"
 
-Some CAs distribute private keys embedded in a PKCS#12 file. Since strongSwan
-is not yet able to read this format directly, the private key part must
-first be extracted using the command
-
-     openssl pkcs12 -nocerts -in moonCert.p12 -out moonKey.pem
-
-if the key file moonKey.pem is to be secured again by a passphrase, or
-
-     openssl pkcs12 -nocerts  -nodes -in moonCert.p12 -out moonKey.pem
+Some CAs distribute private keys embedded in a PKCS#12 file. strongSwan can read
+private keys directly from such a file (end-entity and CA certificates are
+also extracted):
 
-if the private key is to be stored unlocked.
+    : P12 moonCert.p12 "This is my passphrase"
 
 
-6.2 Entering passphrases interactively
-    ----------------------------------
+### Entering passphrases interactively ###
 
 On a VPN gateway you would want to put the passphrase protecting the private
-key file right into /etc/ipsec.secrets as described in the previous paragraph,
+key file right into `/etc/ipsec.secrets` as described in the previous section,
 so that the gateway can be booted in unattended mode.  The risk of keeping
 unencrypted secrets on a server can be minimized by putting the box into a
 locked room.  As long as no one can get root access on the machine the private
 keys are safe.
 
 On a mobile laptop computer the situation is quite different.  The computer can
-be stolen or the user is leaving it unattended so that unauthorized persons
+be stolen or the user may leave it unattended so that unauthorized persons
 can get access to it.  In theses cases it would be preferable not to keep any
-passphrases openly in /etc/ipsec.secrets but to prompt for them interactively
+passphrases openly in `/etc/ipsec.secrets` but to prompt for them interactively
 instead.  This is easily done by defining
 
     : RSA moonKey.pem %prompt
@@ -1287,228 +1161,138 @@ and which causes a passphrase prompt to appear.  To abort entering a passphrase
 enter just a carriage return.
 
 
-6.3 Multiple private keys
-    ---------------------
+## Configuring CA properties - ipsec.conf ##
 
-strongSwan supports multiple private keys. Since the connections defined
-in ipsec.conf can find the correct private key based on the public key
-contained in the certificate assigned by leftcert, default private key
-definitions without specific IDs can be used
-
-    : RSA myKey1.pem "<optional passphrase1>"
-
-    : RSA myKey2.pem "<optional passphrase2>"
-
-
-7. Configuring CA properties - ipsec.conf
-   --------------------------------------
-
-Besides the definition of IPsec connections the ipsec.conf file can also
+Besides the definition of IPsec connections the `ipsec.conf` file can also
 be used to configure a few properties of the certification authorities
 needed to establish the X.509 trust chains.  The following example shows
 some of the parameters that are currently available:
 
     ca strongswan
-       cacert=strongswanCert.pem
-       ocspuri=http://ocsp.strongswan.org:8880
-       crluri=http://crl.strongswan.org/strongswan.crl'
-       crluri2="ldap://ldap.strongswan.org/O=strongSwan, C=CH?certificateRevocationList"
-       auto=add
+        cacert=strongswanCert.pem
+        ocspuri=http://ocsp.strongswan.org:8880
+        crluri=http://crl.strongswan.org/strongswan.crl'
+        crluri2="ldap://ldap.strongswan.org/O=strongSwan, C=CH?certificateRevocationList"
+        auto=add
 
-In a similar way as conn sections are used for connection definitions, an
-arbitrary number of optional ca sections define the basic properties of CAs.
+In a similar way as `conn` sections are used for connection definitions, an
+arbitrary number of optional `ca` sections define the basic properties of CAs.
 
 Each ca section is named with a unique label
 
-       ca strongswan
+    ca strongswan
 
 The only mandatory parameter is
 
-       cacert=strongswanCert.pem
+    cacert=strongswanCert.pem
 
 which points to the CA certificate which usually resides in the default
-directory /etc/ipsec.d/cacerts/ but could also be retrieved via an absolute
+directory `/etc/ipsec.d/cacerts/` but could also be retrieved via an absolute
 path name.
 
 The OCSP URI
 
-       ocspuri=http://ocsp.strongswan.org:8880
+    ocspuri=http://ocsp.strongswan.org:8880
 
 allows to define an individual OCSP server per CA.  Also up to two additional
 CRL distribution points (CDPs) can be defined
 
-       crluri=http://crl.strongswan.org/strongswan.crl'
-       crluri2="ldap://ldap.strongswan.org/O=strongSwan, C=CH?certificateRevocationList"
+    crluri=http://crl.strongswan.org/strongswan.crl'
+    crluri2="ldap://ldap.strongswan.org/O=strongSwan, C=CH?certificateRevocationList"
 
 which are added to any CDPs already present in the received certificates
 themselves.
 
-With the auto=add statement the ca definition is automatically loaded during
-startup.  Setting auto=ignore will ignore the ca section.
+With the `auto=add` statement the `ca` definition is automatically loaded during
+startup.  Setting `auto=ignore` will ignore the `ca` section.
 
 Any parameters which appear in several ca definitions can be put in
-a common ca %default section
+a common `ca %default` section
 
     ca %default
-       crluri=http://crl.strongswan.org/strongswan.crl'
+        crluri=http://crl.strongswan.org/strongswan.crl'
 
 
-8. Monitoring functions
-   --------------------
+## Monitoring functions ##
 
 strongSwan offers the following monitoring functions:
 
-The command
-
-    ipsec listalgs
+| Command             | Action                                            |
+|---------------------|---------------------------------------------------|
+| ipsec listaacerts   | list all Authorization Authority certificates loaded from `/etc/ipsec.d/aacerts/` |
+| ipsec listacerts    | list all X.509 attribute certificates loaded from `/etc/ipsec.d/acerts/` |
+| ipsec listalgs      | list cryptographic algorithms for IKE             |
+| ipsec listcacerts   | list all CA certificates loaded from `/etc/ipsec.d/cacerts/` or received via IKE |
+| ipsec listcainfos   | list all properties defined in `ca` sections in `ipsec.conf` |
+| ipsec listcerts     | list all certificates loaded via `leftcert` and `rightcert` |
+| ipsec listcounters  | list global or connection specific counter values |
+| ipsec listcrls      | list all CLRs loaded from `/etc/ipsec.d/crls/`    |
+| ipsec listocsp      | list contents of the OCSP response cache          |
+| ipsec listocspcerts | list all OCSP signer certificates loaded from `/etc/ipsec.d/ocspcerts/` or received in OCSP responses |
+| ipsec listplugins   | list all loaded plugin features                   |
+| ipsec listpubkeys   | list all raw public keys e.g. loaded via `leftsigkey` and `rightsigkey` |
+| ipsec listall       | all the above commands combined                   |
+| ipsec status        | list concise status information on established connections |
+| ipsec statusall     | list detailed status information on connections |
 
-lists all IKE cryptographic algorithms that are currently
-registered with strongSwan.
 
+## Firewall support functions ##
 
-The command
 
-    ipsec listcerts [--utc]
-
-lists all local certificates, both strongSwan's own and those of
-trusted peer loaded via leftcert and rightcert, respectively.
-
-
-The command
-
-    ipsec listcacerts [--utc]
-
-lists all CA certificates that have been either been loaded from the directory
-/etc/ipsec.d/cacerts/ or received via the IKE protocol.
-
-
-The command
-
-    ipsec listaacerts [--utc]
-
-lists all Authorization Authority certificates that have been loaded from
-the directory /etc/ipsec.d/aacerts/.
-
-
-The command
-
-    ipsec listocspcerts [--utc]
-
-lists all OCSO signer certificates that have been either loaded from
-/etc/ipsec.d/ocspcerts/ or have been received included in the OCSP server
-response.
-
-
-The command
-
-    ipsec listacerts [--utc]
-
-lists all X.509 attribute certificates that have been loaded from the directory
-/etc/ipsec.d/acerts/.
-
-
-The command
-
-    ipsec listcainfos [--utc]
-
-lists the properties defined by the ca definition sections in ipsec.conf.
-
-
-The command
-
-    ipsec listcrls [--utc]
-
-lists all CRLs that have been loaded from /etc/ipsec.d/crls/.
-
-
-The command
-
-
-    ipsec listocsp [--utc]
-
-lists the contents of the OCSP response cache.
-
-
-The command
-
-    ipsec listall [--utc]
-
-is equivalent to using all of the above commands.
-
-
-9. Firewall support functions
-   --------------------------
-
-
-9.1 Environment variables in the updown script
-    ------------------------------------------
+### Environment variables in the updown script ###
 
 strongSwan makes the following environment variables available
-in the updown script indicated by the leftupdown option:
-
-+-------------------------------------------------------------------+
-| Variable               Example                    Comment         |
-|-------------------------------------------------------------------|
-| $PLUTO_PEER_ID         carol at strongswan.org       RFC822_ADDR (1) |
-|-------------------------------------------------------------------|
-| $PLUTO_PEER_PROTOCOL   17                         udp         (2) |
-|-------------------------------------------------------------------|
-| $PLUTO_PEER_PORT       68                         bootpc      (3) |
-|-------------------------------------------------------------------|
-| $PLUTO_PEER_CA         C=CH, O=ACME, CN=Sales CA              (4) |
-|-------------------------------------------------------------------|
-| $PLUTO_MY_ID           @moon.strongswan.org       FQDN        (1) |
-|-------------------------------------------------------------------|
-| $PLUTO_MY_PROTOCOL     17                         udp         (2) |
-|-------------------------------------------------------------------|
-| $PLUTO_MY_PORT         67                         bootps      (3) |
-+-------------------------------------------------------------------+
+in the _updown_ script indicated by the `leftupdown` option:
+
+| Variable              | Example                   | Comment         |
+|-----------------------|---------------------------|-----------------|
+| $PLUTO_PEER_ID        | carol at strongswan.org      | RFC822_ADDR (1) |
+| $PLUTO_PEER_PROTOCOL  | 17                        | udp         (2) |
+| $PLUTO_PEER_PORT      | 68                        | bootpc      (3) |
+| $PLUTO_MY_ID          | moon.strongswan.org       | FQDN        (1) |
+| $PLUTO_MY_PROTOCOL    | 17                        | udp         (2) |
+| $PLUTO_MY_PORT        | 67                        | bootps      (3) |
 
 (1) $PLUTO_PEER_ID/$PLUTO_MY_ID contain the IDs of the two ends
     of an established connection. In our examples these
-    correspond to the strings defined by rightid and leftid,
+    correspond to the strings defined by `rightid` and `leftid`,
     respectively.
 
 (2) $PLUTO_PEER_PROTOCOL/$PLUTO_MY_PROTOCOL contain the protocol
-    defined by the rightprotoport and leftprotoport options,
+    defined by the `rightprotoport` and `leftprotoport` options,
     respectively. Both variables contain the same protocol value.
     The variables take on the value '0' if no protocol has been defined.
 
 (3) $PLUTO_PEER_PORT/$PLUTO_MY_PORT contain the ports defined by
-    the rightprotoport and leftprotoport options, respectively.
+    the `rightprotoport` and `leftprotoport` options, respectively.
     The variables take on the value '0' if no port has been defined.
 
-(4) $PLUTO_PEER_CA contains the distinguished name of the CA that
-    issued the peer's certificate.
-
 There are several more, refer to the provided default script for a documentation
-of these.
+of them.
 
 
-9.2 Automatic insertion and deletion of iptables firewall rules
-    -----------------------------------------------------------
+### Automatic insertion and deletion of iptables firewall rules ###
 
-The default _updown script automatically inserts and deletes dynamic iptables
-firewall rules upon the establishment or teardown, respectively, of an IPsec
-security association.  This feature is activated with the line
+The default `_updown` script automatically inserts and deletes dynamic
+`iptables` firewall rules upon the establishment or teardown, respectively, of
+an IPsec security association.  This feature is activated with the line
 
-   leftfirewall=yes
+    leftfirewall=yes
 
-If you define a local client subnet with a netmask larger than /32 behind
-the gateway then the automatically inserted FORWARD iptables rules will
-not allow to access the internal IP address of the host although it is
-part of the client subnet definition.  If you want additional INPUT and
-OUTPUT iptables rules to be inserted, so that the host itself can be accessed
-then add the following line:
+If you define a `leftsubnet` with a netmask larger than `/32` then the
+automatically inserted _FORWARD_ `iptables` rules will not allow clients to
+access the internal IP address of the gateway even if it is part of that subnet
+definition.  If you want additional _INPUT_ and _OUTPUT_ `iptables` rules to be
+inserted, so that the host itself can be accessed then add the following line:
 
-   lefthostaccess=yes
+    lefthostaccess=yes
 
-The _updown script also features a logging facility which will register the
+The `_updown` script also features a logging facility which will register the
 creation (+) and the expiration (-) of each successfully established VPN
 connection in a special syslog file in the following concise and easily
 readable format:
 
-Jul 19 18:58:38 moon vpn:
-    + @carol.strongswan.org  192.168.0.100 -- 192.168.0.1 == 10.1.0.0/16
-Jul 19 22:15:17 moon vpn:
-    - @carol.strongswan.org  192.168.0.100 -- 192.168.0.1 == 10.1.0.0/16
+    Jul 19 18:58:38 moon vpn:
+        + carol.strongswan.org  192.168.0.100 -- 192.168.0.1 == 10.1.0.0/16
+    Jul 19 22:15:17 moon vpn:
+        - carol.strongswan.org  192.168.0.100 -- 192.168.0.1 == 10.1.0.0/16
diff --git a/aclocal.m4 b/aclocal.m4
index e8f4624..4521f37 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
 
 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
 
@@ -21,7 +21,7 @@ If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically 'autoreconf'.])])
 
 # lib-prefix.m4 serial 7 (gettext-0.18)
-dnl Copyright (C) 2001-2005, 2008-2010 Free Software Foundation, Inc.
+dnl Copyright (C) 2001-2005, 2008-2013 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -417,10 +417,10 @@ fi[]dnl
 # generated from the m4 files accompanying Automake X.Y.
 # (This private macro should not be called outside this file.)
 AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.13'
+[am__api_version='1.14'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.13.3], [],
+m4_if([$1], [1.14.1], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -436,7 +436,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.13.3])dnl
+[AM_AUTOMAKE_VERSION([1.14.1])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@@ -840,6 +840,12 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
 # This macro actually does too much.  Some checks are only needed if
 # your package does certain things.  But this isn't really a big deal.
 
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
 # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
 # AM_INIT_AUTOMAKE([OPTIONS])
 # -----------------------------------------------
@@ -948,7 +954,48 @@ dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
 AC_CONFIG_COMMANDS_PRE(dnl
 [m4_provide_if([_AM_COMPILER_EXEEXT],
   [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
-])
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake at gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi])
 
 dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
 dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
@@ -956,7 +1003,6 @@ dnl mangled by Autoconf and run in a shell conditional statement.
 m4_define([_AC_COMPILER_EXEEXT],
 m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
 
-
 # When config.status generates a header, we must update the stamp-h file.
 # This file resides in the same directory as the config header
 # that is generated.  The stamp files are numbered to have different names.
@@ -1068,38 +1114,6 @@ AC_MSG_RESULT([$_am_result])
 rm -f confinc confmf
 ])
 
-# Copyright (C) 1999-2013 Free Software Foundation, Inc.
-#
-# This file 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.
-
-# AM_PROG_CC_C_O
-# --------------
-# Like AC_PROG_CC_C_O, but changed for automake.
-AC_DEFUN([AM_PROG_CC_C_O],
-[AC_REQUIRE([AC_PROG_CC_C_O])dnl
-AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-AC_REQUIRE_AUX_FILE([compile])dnl
-# FIXME: we rely on the cache variable name because
-# there is no other way.
-set dummy $CC
-am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
-eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
-if test "$am_t" != yes; then
-   # Losing compiler, so override with the script.
-   # FIXME: It is wrong to rewrite CC.
-   # But if we don't then we get into trouble of one sort or another.
-   # A longer-term fix would be to have automake use am__CC in this case,
-   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
-   CC="$am_aux_dir/compile $CC"
-fi
-dnl Make sure AC_PROG_CC is never called again, or it will override our
-dnl setting of CC.
-m4_define([AC_PROG_CC],
-          [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
-])
-
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
 # Copyright (C) 1997-2013 Free Software Foundation, Inc.
@@ -1176,6 +1190,53 @@ AC_DEFUN([_AM_IF_OPTION],
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file 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.
+
 
 # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
 # ---------------------------------------------------------------------------
diff --git a/conf/Makefile.am b/conf/Makefile.am
index 61a0add..373be16 100644
--- a/conf/Makefile.am
+++ b/conf/Makefile.am
@@ -8,6 +8,7 @@ optionstemplatedir = $(templatesdir)/strongswan.d
 pluginstemplatedir = $(templatesdir)/plugins
 
 options = \
+	options/aikgen.opt \
 	options/attest.opt \
 	options/charon.opt \
 	options/charon-logging.opt \
@@ -15,10 +16,12 @@ options = \
 	options/manager.opt \
 	options/medsrv.opt \
 	options/pacman.opt \
+	options/pki.opt \
 	options/pool.opt \
+	options/scepclient.opt \
 	options/starter.opt \
-	options/tnc.opt \
-	options/tools.opt
+	options/swanctl.opt \
+	options/tnc.opt
 
 plugins = \
 	plugins/android_log.opt \
@@ -51,10 +54,10 @@ plugins = \
 	plugins/imv-attestation.opt \
 	plugins/imv-os.opt \
 	plugins/imv-scanner.opt \
+	plugins/imv-swid.opt \
 	plugins/imv-test.opt \
 	plugins/ipseckey.opt \
 	plugins/led.opt \
-	plugins/kernel-klips.opt \
 	plugins/kernel-libipsec.opt \
 	plugins/kernel-netlink.opt \
 	plugins/kernel-pfroute.opt \
@@ -78,6 +81,7 @@ plugins = \
 	plugins/tnccs-20.opt \
 	plugins/unbound.opt \
 	plugins/updown.opt \
+	plugins/vici.opt \
 	plugins/whitelist.opt \
 	plugins/xauth-eap.opt \
 	plugins/xauth-pam.opt
diff --git a/conf/Makefile.in b/conf/Makefile.in
index e14c44e..a0ad980 100644
--- a/conf/Makefile.in
+++ b/conf/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -111,28 +111,6 @@ 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 = 
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-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 = 
-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 =
 DIST_SOURCES =
 am__can_run_installinfo = \
@@ -239,6 +217,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -257,6 +236,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -284,6 +264,7 @@ 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@
@@ -375,6 +356,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -395,6 +377,7 @@ templatesdir = $(pkgdatadir)/templates/config
 optionstemplatedir = $(templatesdir)/strongswan.d
 pluginstemplatedir = $(templatesdir)/plugins
 options = \
+	options/aikgen.opt \
 	options/attest.opt \
 	options/charon.opt \
 	options/charon-logging.opt \
@@ -402,10 +385,12 @@ options = \
 	options/manager.opt \
 	options/medsrv.opt \
 	options/pacman.opt \
+	options/pki.opt \
 	options/pool.opt \
+	options/scepclient.opt \
 	options/starter.opt \
-	options/tnc.opt \
-	options/tools.opt
+	options/swanctl.opt \
+	options/tnc.opt
 
 plugins = \
 	plugins/android_log.opt \
@@ -438,10 +423,10 @@ plugins = \
 	plugins/imv-attestation.opt \
 	plugins/imv-os.opt \
 	plugins/imv-scanner.opt \
+	plugins/imv-swid.opt \
 	plugins/imv-test.opt \
 	plugins/ipseckey.opt \
 	plugins/led.opt \
-	plugins/kernel-klips.opt \
 	plugins/kernel-libipsec.opt \
 	plugins/kernel-netlink.opt \
 	plugins/kernel-pfroute.opt \
@@ -465,6 +450,7 @@ plugins = \
 	plugins/tnccs-20.opt \
 	plugins/unbound.opt \
 	plugins/updown.opt \
+	plugins/vici.opt \
 	plugins/whitelist.opt \
 	plugins/xauth-eap.opt \
 	plugins/xauth-pam.opt
diff --git a/conf/format-options.py b/conf/format-options.py
index fc6e6e1..d046e24 100755
--- a/conf/format-options.py
+++ b/conf/format-options.py
@@ -67,8 +67,8 @@ class ConfigOption:
 		self.desc = []
 		self.options = []
 
-	def __cmp__(self, other):
-		return  cmp(self.name, other.name)
+	def __lt__(self, other):
+		return  self.name < other.name
 
 	def add_paragraph(self):
 		"""Adds a new paragraph to the description"""
@@ -92,8 +92,9 @@ class ConfigOption:
 
 class Parser:
 	"""Parses one or more files of configuration options"""
-	def __init__(self):
+	def __init__(self, sort = True):
 		self.options = []
+		self.sort = sort
 
 	def parse(self, file):
 		"""Parses the given file and adds all options to the internal store"""
@@ -145,7 +146,8 @@ class Parser:
 			found.adopt(option)
 		else:
 			parent.options.append(option)
-			parent.options.sort()
+			if self.sort:
+				parent.options.sort()
 
 	def __get_option(self, parts, create = False):
 		"""Searches/Creates the option (section) based on a list of section names"""
@@ -160,7 +162,8 @@ class Parser:
 					break
 				option = ConfigOption(fullname, section = True)
 				options.append(option)
-				options.sort()
+				if self.sort:
+					options.sort()
 			options = option.options
 		return option
 
@@ -227,31 +230,32 @@ class ConfFormatter:
 		if len(opt.desc):
 			self.__wrapper.initial_indent = '{0}# '.format(self.__indent * indent)
 			self.__wrapper.subsequent_indent = self.__wrapper.initial_indent
-			print format(self.__wrapper.fill(self.__tags.replace(opt.desc[0])))
+			print(self.__wrapper.fill(self.__tags.replace(opt.desc[0])))
 
 	def __print_option(self, opt, indent, commented):
 		"""Print a single option with description and default value"""
 		comment = "# " if commented or opt.commented else ""
 		self.__print_description(opt, indent)
 		if opt.default:
-			print '{0}{1}{2} = {3}'.format(self.__indent * indent, comment, opt.name, opt.default)
+			print('{0}{1}{2} = {3}'.format(self.__indent * indent, comment, opt.name, opt.default))
 		else:
-			print '{0}{1}{2} ='.format(self.__indent * indent, comment, opt.name)
-		print
+			print('{0}{1}{2} ='.format(self.__indent * indent, comment, opt.name))
+		print('')
 
 	def __print_section(self, section, indent, commented):
 		"""Print a section with all options"""
-		comment = "# " if commented or section.commented else ""
+		commented = commented or section.commented
+		comment = "# " if commented else ""
 		self.__print_description(section, indent)
-		print '{0}{1}{2} {{'.format(self.__indent * indent, comment, section.name)
-		print
+		print('{0}{1}{2} {{'.format(self.__indent * indent, comment, section.name))
+		print('')
 		for o in sorted(section.options, key=attrgetter('section')):
 			if o.section:
-				self.__print_section(o, indent + 1, section.commented)
+				self.__print_section(o, indent + 1, commented)
 			else:
-				self.__print_option(o, indent + 1, section.commented)
-		print '{0}{1}}}'.format(self.__indent * indent, comment)
-		print
+				self.__print_option(o, indent + 1, commented)
+		print('{0}{1}}}'.format(self.__indent * indent, comment))
+		print('')
 
 	def format(self, options):
 		"""Print a list of options"""
@@ -282,14 +286,14 @@ class ManFormatter:
 		if option.section and not len(option.desc):
 			return
 		if option.section:
-			print '.TP\n.B {0}\n.br'.format(option.fullname)
+			print('.TP\n.B {0}\n.br'.format(option.fullname))
 		else:
-			print '.TP'
+			print('.TP')
 			default = option.default if option.default else ''
-			print '.BR {0} " [{1}]"'.format(option.fullname, default)
+			print('.BR {0} " [{1}]"'.format(option.fullname, default))
 		for para in option.desc if len(option.desc) < 2 else option.desc[1:]:
-			print self.__groffize(self.__wrapper.fill(para))
-			print ''
+			print(self.__groffize(self.__wrapper.fill(para)))
+			print('')
 
 	def format(self, options):
 		"""Print a list of options"""
@@ -309,9 +313,12 @@ options.add_option("-f", "--format", dest="format", type="choice", choices=["con
 options.add_option("-r", "--root", dest="root", metavar="NAME",
 				   help="root section of which options are printed, "
 				   "if not found everything is printed")
+options.add_option("-n", "--nosort", action="store_false", dest="sort",
+				   default=True, help="do not sort sections alphabetically")
+
 (opts, args) = options.parse_args()
 
-parser = Parser()
+parser = Parser(opts.sort)
 if len(args):
 	for filename in args:
 		try:
diff --git a/conf/options/aikgen.conf b/conf/options/aikgen.conf
new file mode 100644
index 0000000..10d362f
--- /dev/null
+++ b/conf/options/aikgen.conf
@@ -0,0 +1,7 @@
+aikgen {
+
+    # Plugins to load in ipsec aikgen tool.
+    # load =
+
+}
+
diff --git a/conf/options/aikgen.opt b/conf/options/aikgen.opt
new file mode 100644
index 0000000..2d33947
--- /dev/null
+++ b/conf/options/aikgen.opt
@@ -0,0 +1,2 @@
+aikgen.load =
+	Plugins to load in ipsec aikgen tool.
diff --git a/conf/options/charon.conf b/conf/options/charon.conf
index 5cab2b1..ec3a39a 100644
--- a/conf/options/charon.conf
+++ b/conf/options/charon.conf
@@ -1,6 +1,9 @@
 # Options for the charon IKE daemon.
 charon {
 
+    # Accept unencrypted ID and HASH payloads in IKEv1 Main Mode.
+    # accept_unencrypted_mainmode_messages = no
+
     # Maximum number of half-open IKE_SAs for a single peer IP.
     # block_threshold = 5
 
@@ -131,6 +134,11 @@ charon {
     # will be allocated.
     # port_nat_t = 4500
 
+    # By default public IPv6 addresses are preferred over temporary ones (RFC
+    # 4941), to make connections more stable. Enable this option to reverse
+    # this.
+    # prefer_temporary_addrs = no
+
     # Process RTM_NEWROUTE and RTM_DELROUTE events.
     # process_route = yes
 
@@ -254,6 +262,18 @@ charon {
 
     }
 
+    # Section containing a list of scripts (name = path) that are executed when
+    # the daemon is started.
+    start-scripts {
+
+    }
+
+    # Section containing a list of scripts (name = path) that are executed when
+    # the daemon is terminated.
+    stop-scripts {
+
+    }
+
     tls {
 
         # List of TLS encryption ciphers.
diff --git a/conf/options/charon.opt b/conf/options/charon.opt
index c6f4f1e..1eb1b88 100644
--- a/conf/options/charon.opt
+++ b/conf/options/charon.opt
@@ -8,6 +8,21 @@ charon {}
 	**charon-cmd** instead of **charon**). For many options defaults can be
 	defined in the **libstrongswan** section.
 
+charon.accept_unencrypted_mainmode_messages = no
+	Accept unencrypted ID and HASH payloads in IKEv1 Main Mode.
+
+	Accept unencrypted ID and HASH payloads in IKEv1 Main Mode.
+
+	Some implementations send the third Main Mode message unencrypted, probably
+	to find the PSKs for the specified ID for authentication. This is very
+	similar to Aggressive Mode, and has the same security implications: A
+	passive attacker can sniff the negotiated Identity, and start brute forcing
+	the PSK using the HASH payload.
+
+	It is recommended to keep this option to no, unless you know exactly
+	what the implications are and require compatibility to such devices (for
+	example, some SonicWall boxes).
+
 charon.block_threshold = 5
 	Maximum number of half-open IKE_SAs for a single peer IP.
 
@@ -196,6 +211,10 @@ charon.port_nat_t = 4500
 	allocated.  Has to be different from **charon.port**, otherwise a random
 	port will be allocated.
 
+charon.prefer_temporary_addrs = no
+	By default public IPv6 addresses are preferred over temporary ones (RFC
+	4941), to make connections more stable. Enable this option to reverse this.
+
 charon.process_route = yes
 	Process RTM_NEWROUTE and RTM_DELROUTE events.
 
@@ -256,6 +275,14 @@ charon.send_delay_type = 0
 charon.send_vendor_id = no
 	Send strongSwan vendor ID payload
 
+charon.start-scripts {}
+	Section containing a list of scripts (name = path) that are executed when
+	the daemon is started.
+
+charon.stop-scripts {}
+	Section containing a list of scripts (name = path) that are executed when
+	the daemon is terminated.
+
 charon.threads = 16
 	Number of worker threads in charon.
 
diff --git a/conf/options/pki.conf b/conf/options/pki.conf
new file mode 100644
index 0000000..f64a091
--- /dev/null
+++ b/conf/options/pki.conf
@@ -0,0 +1,7 @@
+pki {
+
+    # Plugins to load in ipsec pki tool.
+    # load =
+
+}
+
diff --git a/conf/options/pki.opt b/conf/options/pki.opt
new file mode 100644
index 0000000..c57dcc8
--- /dev/null
+++ b/conf/options/pki.opt
@@ -0,0 +1,2 @@
+pki.load =
+	Plugins to load in ipsec pki tool.
diff --git a/conf/options/scepclient.conf b/conf/options/scepclient.conf
new file mode 100644
index 0000000..0b1a131
--- /dev/null
+++ b/conf/options/scepclient.conf
@@ -0,0 +1,7 @@
+scepclient {
+
+    # Plugins to load in ipsec scepclient tool.
+    # load =
+
+}
+
diff --git a/conf/options/scepclient.opt b/conf/options/scepclient.opt
new file mode 100644
index 0000000..7e30f5c
--- /dev/null
+++ b/conf/options/scepclient.opt
@@ -0,0 +1,2 @@
+scepclient.load =
+	Plugins to load in ipsec scepclient tool.
diff --git a/conf/options/swanctl.conf b/conf/options/swanctl.conf
new file mode 100644
index 0000000..cb18239
--- /dev/null
+++ b/conf/options/swanctl.conf
@@ -0,0 +1,7 @@
+swanctl {
+
+    # Plugins to load in swanctl.
+    # load =
+
+}
+
diff --git a/conf/options/swanctl.opt b/conf/options/swanctl.opt
new file mode 100644
index 0000000..f78b4bc
--- /dev/null
+++ b/conf/options/swanctl.opt
@@ -0,0 +1,2 @@
+swanctl.load =
+	Plugins to load in swanctl.
\ No newline at end of file
diff --git a/conf/options/tools.conf b/conf/options/tools.conf
deleted file mode 100644
index 781635c..0000000
--- a/conf/options/tools.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-pki {
-
-    # Plugins to load in ipsec pki tool.
-    # load =
-
-}
-
-scepclient {
-
-    # Plugins to load in ipsec scepclient tool.
-    # load =
-
-}
-
diff --git a/conf/options/tools.opt b/conf/options/tools.opt
deleted file mode 100644
index 72a49de..0000000
--- a/conf/options/tools.opt
+++ /dev/null
@@ -1,5 +0,0 @@
-pki.load =
-	Plugins to load in ipsec pki tool.
-
-scepclient.load =
-	Plugins to load in ipsec scepclient tool.
diff --git a/conf/plugins/eap-tnc.conf b/conf/plugins/eap-tnc.conf
index aca72f1..27ef136 100644
--- a/conf/plugins/eap-tnc.conf
+++ b/conf/plugins/eap-tnc.conf
@@ -9,7 +9,7 @@ eap-tnc {
 
     # IF-TNCCS protocol version to be used (tnccs-1.1, tnccs-2.0,
     # tnccs-dynamic).
-    # protocol = tnccs-1.1
+    # protocol = tnccs-2.0
 
 }
 
diff --git a/conf/plugins/eap-tnc.opt b/conf/plugins/eap-tnc.opt
index 8e060ce..5593152 100644
--- a/conf/plugins/eap-tnc.opt
+++ b/conf/plugins/eap-tnc.opt
@@ -1,6 +1,6 @@
 charon.plugins.eap-tnc.max_message_count = 10
 	Maximum number of processed EAP-TNC packets (0 = no limit).
 
-charon.plugins.eap-tnc.protocol = tnccs-1.1
+charon.plugins.eap-tnc.protocol = tnccs-2.0
 	IF-TNCCS protocol version to be used (_tnccs-1.1_, _tnccs-2.0_,
 	_tnccs-dynamic_).
diff --git a/conf/plugins/eap-ttls.conf b/conf/plugins/eap-ttls.conf
index 5229625..0614dcb 100644
--- a/conf/plugins/eap-ttls.conf
+++ b/conf/plugins/eap-ttls.conf
@@ -23,6 +23,9 @@ eap-ttls {
     # Start phase2 EAP TNC protocol after successful client authentication.
     # phase2_tnc = no
 
+    # Phase2 EAP TNC transport protocol (pt as IETF standard or legacy tnc)
+    # phase2_tnc_method = pt
+
     # Request peer authentication based on a client certificate.
     # request_peer_auth = no
 
diff --git a/conf/plugins/eap-ttls.opt b/conf/plugins/eap-ttls.opt
index 21a6cb6..7dcee82 100644
--- a/conf/plugins/eap-ttls.opt
+++ b/conf/plugins/eap-ttls.opt
@@ -16,5 +16,8 @@ charon.plugins.eap-ttls.phase2_piggyback = no
 charon.plugins.eap-ttls.phase2_tnc = no
 	Start phase2 EAP TNC protocol after successful client authentication.
 
+charon.plugins.eap-ttls.phase2_tnc_method = pt
+	Phase2 EAP TNC transport protocol (_pt_ as IETF standard or legacy _tnc_)
+
 charon.plugins.eap-ttls.request_peer_auth = no
 	Request peer authentication based on a client certificate.
diff --git a/conf/plugins/imc-attestation.conf b/conf/plugins/imc-attestation.conf
index 2d8deaa..eed706f 100644
--- a/conf/plugins/imc-attestation.conf
+++ b/conf/plugins/imc-attestation.conf
@@ -1,29 +1,8 @@
 imc-attestation {
 
-    # AIK encrypted private key blob file.
-    # aik_blob =
-
-    # AIK certificate file.
-    # aik_cert =
-
-    # AIK public key file.
-    # aik_key =
-
     # Whether to load the plugin. Can also be an integer to increase the
     # priority of this plugin.
     load = yes
 
-    # Enforce mandatory Diffie-Hellman groups.
-    # mandatory_dh_groups = yes
-
-    # DH nonce length.
-    # nonce_len = 20
-
-    # Whether to send pcr_before and pcr_after info.
-    # pcr_info = yes
-
-    # Use Quote2 AIK signature instead of Quote signature.
-    # use_quote2 = yes
-
 }
 
diff --git a/conf/plugins/imc-attestation.opt b/conf/plugins/imc-attestation.opt
index aaac4c2..9b60b9e 100644
--- a/conf/plugins/imc-attestation.opt
+++ b/conf/plugins/imc-attestation.opt
@@ -1,20 +1,20 @@
-charon.plugins.imc-attestation.aik_blob =
+libimcv.plugins.imc-attestation.aik_blob =
 	AIK encrypted private key blob file.
 
-charon.plugins.imc-attestation.aik_cert =
+libimcv.plugins.imc-attestation.aik_cert =
 	AIK certificate file.
 
-charon.plugins.imc-attestation.aik_key =
+libimcv.plugins.imc-attestation.aik_pubkey =
 	AIK public key file.
 
-charon.plugins.imc-attestation.mandatory_dh_groups = yes
+libimcv.plugins.imc-attestation.mandatory_dh_groups = yes
 	Enforce mandatory Diffie-Hellman groups.
 
-charon.plugins.imc-attestation.nonce_len = 20
+libimcv.plugins.imc-attestation.nonce_len = 20
 	DH nonce length.
 
-charon.plugins.imc-attestation.use_quote2 = yes
+libimcv.plugins.imc-attestation.use_quote2 = yes
 	Use Quote2 AIK signature instead of Quote signature.
 
-charon.plugins.imc-attestation.pcr_info = yes
+libimcv.plugins.imc-attestation.pcr_info = no
 	Whether to send pcr_before and pcr_after info.
diff --git a/conf/plugins/imc-os.conf b/conf/plugins/imc-os.conf
index 1d245d3..56b2182 100644
--- a/conf/plugins/imc-os.conf
+++ b/conf/plugins/imc-os.conf
@@ -4,8 +4,5 @@ imc-os {
     # priority of this plugin.
     load = yes
 
-    # Send operating system info without being prompted.
-    # push_info = yes
-
 }
 
diff --git a/conf/plugins/imc-os.opt b/conf/plugins/imc-os.opt
index 2a6333f..4f559f2 100644
--- a/conf/plugins/imc-os.opt
+++ b/conf/plugins/imc-os.opt
@@ -1,2 +1,14 @@
-charon.plugins.imc-os.push_info = yes
+libimcv.plugins.imc-os.device_cert =
+	Manually set the path to the client device certificate
+    (e.g. /etc/pts/aikCert.der)
+
+libimcv.plugins.imc-os.device_id =
+	Manually set the client device ID in hexadecimal format
+   (e.g. 1083f03988c9762703b1c1080c2e46f72b99cc31)
+
+libimcv.plugins.imc-os.device_pubkey =
+	Manually set the path to the client device public key
+    (e.g. /etc/pts/aikPub.der)
+
+libimcv.plugins.imc-os.push_info = yes
 	Send operating system info without being prompted.
diff --git a/conf/plugins/imc-scanner.conf b/conf/plugins/imc-scanner.conf
index 7f2f531..fb05a08 100644
--- a/conf/plugins/imc-scanner.conf
+++ b/conf/plugins/imc-scanner.conf
@@ -4,8 +4,5 @@ imc-scanner {
     # priority of this plugin.
     load = yes
 
-    # Send open listening ports without being prompted.
-    # push_info = yes
-
 }
 
diff --git a/conf/plugins/imc-scanner.opt b/conf/plugins/imc-scanner.opt
index 84e6dfa..9cc12b9 100644
--- a/conf/plugins/imc-scanner.opt
+++ b/conf/plugins/imc-scanner.opt
@@ -1,2 +1,2 @@
-charon.plugins.imc-scanner.push_info = yes
+libimcv.plugins.imc-scanner.push_info = yes
 	Send open listening ports without being prompted.
diff --git a/conf/plugins/imc-swid.conf b/conf/plugins/imc-swid.conf
index 8b33171..4893703 100644
--- a/conf/plugins/imc-swid.conf
+++ b/conf/plugins/imc-swid.conf
@@ -4,8 +4,5 @@ imc-swid {
     # priority of this plugin.
     load = yes
 
-    # Directory where SWID tags are located.
-    # swid_directory = ${prefix}/share
-
 }
 
diff --git a/conf/plugins/imc-swid.opt b/conf/plugins/imc-swid.opt
index 67f7c79..74490c1 100644
--- a/conf/plugins/imc-swid.opt
+++ b/conf/plugins/imc-swid.opt
@@ -1,2 +1,11 @@
-charon.plugins.imc-swid.swid_directory = ${prefix}/share
+libimcv.plugins.imc-swid.swid_directory = ${prefix}/share
 	Directory where SWID tags are located.
+
+libimcv.plugins.imc-swid.swid_generator = /usr/local/bin/swid_generator
+	SWID generator command to be executed.
+
+libimcv.plugins.imc-swid.swid_pretty = FALSE
+	Generate XML-encoded SWID tags with pretty indentation.
+
+libimcv.plugins.imc-swid.swid_full = FALSE
+	Include file information in the XML-encoded SWID tags.
diff --git a/conf/plugins/imc-test.conf b/conf/plugins/imc-test.conf
index 0d66e3d..4deac76 100644
--- a/conf/plugins/imc-test.conf
+++ b/conf/plugins/imc-test.conf
@@ -1,23 +1,8 @@
 imc-test {
 
-    # Number of additional IMC IDs.
-    # additional_ids = 0
-
-    # Command to be sent to the Test IMV.
-    # command = none
-
-    # Size of dummy attribute to be sent to the Test IMV (0 = disabled).
-    # dummy_size = 0
-
     # Whether to load the plugin. Can also be an integer to increase the
     # priority of this plugin.
     load = yes
 
-    # Do a handshake retry.
-    # retry = no
-
-    # Command to be sent to the Test IMV in the handshake retry.
-    # retry_command =
-
 }
 
diff --git a/conf/plugins/imc-test.opt b/conf/plugins/imc-test.opt
index c3169b5..e15b069 100644
--- a/conf/plugins/imc-test.opt
+++ b/conf/plugins/imc-test.opt
@@ -1,14 +1,14 @@
-charon.plugins.imc-test.additional_ids = 0
+libimcv.plugins.imc-test.additional_ids = 0
 	Number of additional IMC IDs.
 
-charon.plugins.imc-test.command = none
+libimcv.plugins.imc-test.command = none
 	Command to be sent to the Test IMV.
 
-charon.plugins.imc-test.dummy_size = 0
+libimcv.plugins.imc-test.dummy_size = 0
 	Size of dummy attribute to be sent to the Test IMV (0 = disabled).
 
-charon.plugins.imc-test.retry = no
+libimcv.plugins.imc-test.retry = no
 	Do a handshake retry.
 
-charon.plugins.imc-test.retry_command =
+libimcv.plugins.imc-test.retry_command =
 	Command to be sent to the Test IMV in the handshake retry.
diff --git a/conf/plugins/imv-attestation.conf b/conf/plugins/imv-attestation.conf
index 3a1a7f2..29a4209 100644
--- a/conf/plugins/imv-attestation.conf
+++ b/conf/plugins/imv-attestation.conf
@@ -1,45 +1,8 @@
-imc-attestation {
-
-    # Dummy data if the TBOOT log is not retrieved.
-    # pcr17_after =
-
-    # Dummy data if the TBOOT log is not retrieved.
-    # pcr17_before =
-
-    # Dummy data if the TBOOT log is not retrieved.
-    # pcr17_meas =
-
-    # Dummy data if the TBOOT log is not retrieved.
-    # pcr18_after =
-
-    # Dummy data if the TBOOT log is not retrieved.
-    # pcr18_before =
-
-    # Dummy data if the TBOOT log is not retrieved.
-    # pcr18_meas =
-
-}
-
 imv-attestation {
 
-    # Path to directory with AIK cacerts.
-    # cadir =
-
-    # Preferred Diffie-Hellman group.
-    # dh_group = ecp256
-
-    # Preferred measurement hash algorithm.
-    # hash_algorithm = sha256
-
     # Whether to load the plugin. Can also be an integer to increase the
     # priority of this plugin.
     load = yes
 
-    # Enforce mandatory Diffie-Hellman groups.
-    # mandatory_dh_groups = yes
-
-    # DH minimum nonce length.
-    # min_nonce_len = 0
-
 }
 
diff --git a/conf/plugins/imv-attestation.opt b/conf/plugins/imv-attestation.opt
index f266281..3ad5162 100644
--- a/conf/plugins/imv-attestation.opt
+++ b/conf/plugins/imv-attestation.opt
@@ -1,32 +1,32 @@
-charon.plugins.imv-attestation.cadir =
+libimcv.plugins.imv-attestation.cadir =
 	Path to directory with AIK cacerts.
 
-charon.plugins.imv-attestation.mandatory_dh_groups = yes
+libimcv.plugins.imv-attestation.mandatory_dh_groups = yes
 	Enforce mandatory Diffie-Hellman groups.
 
-charon.plugins.imv-attestation.dh_group = ecp256
+libimcv.plugins.imv-attestation.dh_group = ecp256
 	Preferred Diffie-Hellman group.
 
-charon.plugins.imv-attestation.hash_algorithm = sha256
+libimcv.plugins.imv-attestation.hash_algorithm = sha256
 	Preferred measurement hash algorithm.
 
-charon.plugins.imv-attestation.min_nonce_len = 0
+libimcv.plugins.imv-attestation.min_nonce_len = 0
 	DH minimum nonce length.
 
-charon.plugins.imc-attestation.pcr17_after
+libimcv.plugins.imc-attestation.pcr17_after
 	Dummy data if the TBOOT log is not retrieved.
 
-charon.plugins.imc-attestation.pcr17_before
+libimcv.plugins.imc-attestation.pcr17_before
 	Dummy data if the TBOOT log is not retrieved.
 
-charon.plugins.imc-attestation.pcr17_meas
+libimcv.plugins.imc-attestation.pcr17_meas
 	Dummy data if the TBOOT log is not retrieved.
 
-charon.plugins.imc-attestation.pcr18_after
+libimcv.plugins.imc-attestation.pcr18_after
 	Dummy data if the TBOOT log is not retrieved.
 
-charon.plugins.imc-attestation.pcr18_before
+libimcv.plugins.imc-attestation.pcr18_before
 	Dummy data if the TBOOT log is not retrieved.
 
-charon.plugins.imc-attestation.pcr18_meas
+libimcv.plugins.imc-attestation.pcr18_meas
 	Dummy data if the TBOOT log is not retrieved.
diff --git a/conf/plugins/imv-os.conf b/conf/plugins/imv-os.conf
index 8f0da37..f2786cc 100644
--- a/conf/plugins/imv-os.conf
+++ b/conf/plugins/imv-os.conf
@@ -4,8 +4,5 @@ imv-os {
     # priority of this plugin.
     load = yes
 
-    # URI pointing to operating system remediation instructions.
-    # remediation_uri =
-
 }
 
diff --git a/conf/plugins/imv-os.opt b/conf/plugins/imv-os.opt
index eab9262..fe83bb6 100644
--- a/conf/plugins/imv-os.opt
+++ b/conf/plugins/imv-os.opt
@@ -1,2 +1,2 @@
-charon.plugins.imv-os.remediation_uri =
+libimcv.plugins.imv-os.remediation_uri =
 	URI pointing to operating system remediation instructions.
diff --git a/conf/plugins/imv-scanner.conf b/conf/plugins/imv-scanner.conf
index 25719d0..4b9da8f 100644
--- a/conf/plugins/imv-scanner.conf
+++ b/conf/plugins/imv-scanner.conf
@@ -4,8 +4,5 @@ imv-scanner {
     # priority of this plugin.
     load = yes
 
-    # URI pointing to scanner remediation instructions.
-    # remediation_uri =
-
 }
 
diff --git a/conf/plugins/imv-scanner.opt b/conf/plugins/imv-scanner.opt
index 7af8749..d23c6ba 100644
--- a/conf/plugins/imv-scanner.opt
+++ b/conf/plugins/imv-scanner.opt
@@ -1,2 +1,2 @@
-charon.plugins.imv-scanner.remediation_uri =
+libimcv.plugins.imv-scanner.remediation_uri =
 	URI pointing to scanner remediation instructions.
diff --git a/conf/plugins/imv-swid.conf b/conf/plugins/imv-swid.conf
new file mode 100644
index 0000000..bfd49bd
--- /dev/null
+++ b/conf/plugins/imv-swid.conf
@@ -0,0 +1,8 @@
+imv-swid {
+
+    # Whether to load the plugin. Can also be an integer to increase the
+    # priority of this plugin.
+    load = yes
+
+}
+
diff --git a/conf/plugins/imv-swid.opt b/conf/plugins/imv-swid.opt
new file mode 100644
index 0000000..d451c78
--- /dev/null
+++ b/conf/plugins/imv-swid.opt
@@ -0,0 +1,5 @@
+libimcv.plugins.imv-swid.rest_api_uri = 
+	HTTP URI of the SWID REST API.
+
+libimcv.plugins.imv-swid.rest_api_timeout = 120
+	Timeout of SWID REST API HTTP POST transaction.
diff --git a/conf/plugins/imv-test.conf b/conf/plugins/imv-test.conf
index 9bd2487..b268765 100644
--- a/conf/plugins/imv-test.conf
+++ b/conf/plugins/imv-test.conf
@@ -4,8 +4,5 @@ imv-test {
     # priority of this plugin.
     load = yes
 
-    # Number of IMC-IMV retry rounds.
-    # rounds = 0
-
 }
 
diff --git a/conf/plugins/imv-test.opt b/conf/plugins/imv-test.opt
index 2cbddc8..196559e 100644
--- a/conf/plugins/imv-test.opt
+++ b/conf/plugins/imv-test.opt
@@ -1,2 +1,2 @@
-charon.plugins.imv-test.rounds = 0
+libimcv.plugins.imv-test.rounds = 0
 	Number of IMC-IMV retry rounds.
diff --git a/conf/plugins/kernel-klips.conf b/conf/plugins/kernel-klips.conf
deleted file mode 100644
index 10ca308..0000000
--- a/conf/plugins/kernel-klips.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-kernel-klips {
-
-    # Number of ipsecN devices.
-    # ipsec_dev_count = 4
-
-    # Set MTU of ipsecN device.
-    # ipsec_dev_mtu = 0
-
-    # Whether to load the plugin. Can also be an integer to increase the
-    # priority of this plugin.
-    load = yes
-
-}
-
diff --git a/conf/plugins/kernel-klips.opt b/conf/plugins/kernel-klips.opt
deleted file mode 100644
index ad9806e..0000000
--- a/conf/plugins/kernel-klips.opt
+++ /dev/null
@@ -1,5 +0,0 @@
-charon.plugins.kernel-klips.ipsec_dev_count = 4
-	Number of ipsecN devices.
-
-charon.plugins.kernel-klips.ipsec_dev_mtu = 0
-	Set MTU of ipsecN device.
diff --git a/conf/plugins/load-tester.conf b/conf/plugins/load-tester.conf
index e69c029..17281ba 100644
--- a/conf/plugins/load-tester.conf
+++ b/conf/plugins/load-tester.conf
@@ -16,6 +16,10 @@ load-tester {
     # Seconds to start CHILD_SA rekeying after setup.
     # child_rekey = 600
 
+    # URI to a CRL to include as certificate distribution point in generated
+    # certificates.
+    # crl =
+
     # Delay between initiatons for each thread.
     # delay = 0
 
diff --git a/conf/plugins/load-tester.opt b/conf/plugins/load-tester.opt
index 7afe326..e68adec 100644
--- a/conf/plugins/load-tester.opt
+++ b/conf/plugins/load-tester.opt
@@ -20,6 +20,10 @@ charon.plugins.load-tester.ca_dir =
 charon.plugins.load-tester.child_rekey = 600
 	Seconds to start CHILD_SA rekeying after setup.
 
+charon.plugins.load-tester.crl
+	URI to a CRL to include as certificate distribution point in generated
+	certificates.
+
 charon.plugins.load-tester.delay = 0
 	Delay between initiatons for each thread.
 
diff --git a/conf/plugins/vici.conf b/conf/plugins/vici.conf
new file mode 100644
index 0000000..08fa586
--- /dev/null
+++ b/conf/plugins/vici.conf
@@ -0,0 +1,11 @@
+vici {
+
+    # Whether to load the plugin. Can also be an integer to increase the
+    # priority of this plugin.
+    load = yes
+
+    # Socket the vici plugin serves clients.
+    # socket = unix://${piddir}/charon.vici
+
+}
+
diff --git a/conf/plugins/vici.opt b/conf/plugins/vici.opt
new file mode 100644
index 0000000..0fca873
--- /dev/null
+++ b/conf/plugins/vici.opt
@@ -0,0 +1,2 @@
+charon.plugins.vici.socket = unix://${piddir}/charon.vici
+	Socket the vici plugin serves clients.
diff --git a/conf/strongswan.conf.5.main b/conf/strongswan.conf.5.main
index 12fde49..d93c208 100644
--- a/conf/strongswan.conf.5.main
+++ b/conf/strongswan.conf.5.main
@@ -1,4 +1,8 @@
 .TP
+.BR aikgen.load " []"
+Plugins to load in ipsec aikgen tool.
+
+.TP
 .BR attest.database " []"
 File measurement information database URI. If it contains a password, make sure
 to adjust the permissions of the config file accordingly.
@@ -28,6 +32,20 @@ in the
 section.
 
 .TP
+.BR charon.accept_unencrypted_mainmode_messages " [no]"
+Accept unencrypted ID and HASH payloads in IKEv1 Main Mode.
+
+Some implementations send the third Main Mode message unencrypted, probably to
+find the PSKs for the specified ID for authentication. This is very similar to
+Aggressive Mode, and has the same security implications: A passive attacker can
+sniff the negotiated Identity, and start brute forcing the PSK using the HASH
+payload.
+
+It is recommended to keep this option to no, unless you know exactly what the
+implications are and require compatibility to such devices (for example, some
+SonicWall boxes).
+
+.TP
 .BR charon.block_threshold " [5]"
 Maximum number of half\-open IKE_SAs for a single peer IP.
 
@@ -666,7 +684,7 @@ Maximum number of processed EAP\-TLS packets (0 = no limit).
 Maximum number of processed EAP\-TNC packets (0 = no limit).
 
 .TP
-.BR charon.plugins.eap-tnc.protocol " [tnccs-1.1]"
+.BR charon.plugins.eap-tnc.protocol " [tnccs-2.0]"
 IF\-TNCCS protocol version to be used 
 .RI "(" "tnccs\-1.1" ","
 .RI "" "tnccs\-2.0" ","
@@ -698,6 +716,14 @@ Phase2 EAP Identity request piggybacked by server onto TLS Finished message.
 Start phase2 EAP TNC protocol after successful client authentication.
 
 .TP
+.BR charon.plugins.eap-ttls.phase2_tnc_method " [pt]"
+Phase2 EAP TNC transport protocol 
+.RI "(" "pt" ""
+as IETF standard or legacy
+.RI "" "tnc" ")"
+
+
+.TP
 .BR charon.plugins.eap-ttls.request_peer_auth " [no]"
 Request peer authentication based on a client certificate.
 
@@ -735,134 +761,10 @@ to 0 to disable.
 .TP
 .BR charon.plugins.ha.segment_count " [1]"
 .TP
-.BR charon.plugins.imc-attestation.aik_blob " []"
-AIK encrypted private key blob file.
-
-.TP
-.BR charon.plugins.imc-attestation.aik_cert " []"
-AIK certificate file.
-
-.TP
-.BR charon.plugins.imc-attestation.aik_key " []"
-AIK public key file.
-
-.TP
-.BR charon.plugins.imc-attestation.mandatory_dh_groups " [yes]"
-Enforce mandatory Diffie\-Hellman groups.
-
-.TP
-.BR charon.plugins.imc-attestation.nonce_len " [20]"
-DH nonce length.
-
-.TP
-.BR charon.plugins.imc-attestation.pcr17_after " []"
-Dummy data if the TBOOT log is not retrieved.
-
-.TP
-.BR charon.plugins.imc-attestation.pcr17_before " []"
-Dummy data if the TBOOT log is not retrieved.
-
-.TP
-.BR charon.plugins.imc-attestation.pcr17_meas " []"
-Dummy data if the TBOOT log is not retrieved.
-
-.TP
-.BR charon.plugins.imc-attestation.pcr18_after " []"
-Dummy data if the TBOOT log is not retrieved.
-
-.TP
-.BR charon.plugins.imc-attestation.pcr18_before " []"
-Dummy data if the TBOOT log is not retrieved.
-
-.TP
-.BR charon.plugins.imc-attestation.pcr18_meas " []"
-Dummy data if the TBOOT log is not retrieved.
-
-.TP
-.BR charon.plugins.imc-attestation.pcr_info " [yes]"
-Whether to send pcr_before and pcr_after info.
-
-.TP
-.BR charon.plugins.imc-attestation.use_quote2 " [yes]"
-Use Quote2 AIK signature instead of Quote signature.
-
-.TP
-.BR charon.plugins.imc-os.push_info " [yes]"
-Send operating system info without being prompted.
-
-.TP
-.BR charon.plugins.imc-scanner.push_info " [yes]"
-Send open listening ports without being prompted.
-
-.TP
-.BR charon.plugins.imc-swid.swid_directory " [${prefix}/share]"
-Directory where SWID tags are located.
-
-.TP
-.BR charon.plugins.imc-test.additional_ids " [0]"
-Number of additional IMC IDs.
-
-.TP
-.BR charon.plugins.imc-test.command " [none]"
-Command to be sent to the Test IMV.
-
-.TP
-.BR charon.plugins.imc-test.dummy_size " [0]"
-Size of dummy attribute to be sent to the Test IMV (0 = disabled).
-
-.TP
-.BR charon.plugins.imc-test.retry " [no]"
-Do a handshake retry.
-
-.TP
-.BR charon.plugins.imc-test.retry_command " []"
-Command to be sent to the Test IMV in the handshake retry.
-
-.TP
-.BR charon.plugins.imv-attestation.cadir " []"
-Path to directory with AIK cacerts.
-
-.TP
-.BR charon.plugins.imv-attestation.dh_group " [ecp256]"
-Preferred Diffie\-Hellman group.
-
-.TP
-.BR charon.plugins.imv-attestation.hash_algorithm " [sha256]"
-Preferred measurement hash algorithm.
-
-.TP
-.BR charon.plugins.imv-attestation.mandatory_dh_groups " [yes]"
-Enforce mandatory Diffie\-Hellman groups.
-
-.TP
-.BR charon.plugins.imv-attestation.min_nonce_len " [0]"
-DH minimum nonce length.
-
-.TP
-.BR charon.plugins.imv-os.remediation_uri " []"
-URI pointing to operating system remediation instructions.
-
-.TP
-.BR charon.plugins.imv-scanner.remediation_uri " []"
-URI pointing to scanner remediation instructions.
-
-.TP
-.BR charon.plugins.imv-test.rounds " [0]"
-Number of IMC\-IMV retry rounds.
-
-.TP
 .BR charon.plugins.ipseckey.enable " [no]"
 Enable fetching of IPSECKEY RRs via DNS.
 
 .TP
-.BR charon.plugins.kernel-klips.ipsec_dev_count " [4]"
-Number of ipsecN devices.
-
-.TP
-.BR charon.plugins.kernel-klips.ipsec_dev_mtu " [0]"
-Set MTU of ipsecN device.
-
-.TP
 .BR charon.plugins.kernel-libipsec.allow_peer_ts " [no]"
 Allow that the remote traffic selector equals the IKE peer. The route installed
 for such traffic (via TUN device) usually prevents further IKE traffic. The
@@ -928,6 +830,11 @@ Directory to load (intermediate) CA certificates from.
 Seconds to start CHILD_SA rekeying after setup.
 
 .TP
+.BR charon.plugins.load-tester.crl " []"
+URI to a CRL to include as certificate distribution point in generated
+certificates.
+
+.TP
 .BR charon.plugins.load-tester.delay " [0]"
 Delay between initiatons for each thread.
 
@@ -1360,6 +1267,10 @@ Config or IKEv2 Config Payloads (if enabled they can't be handled by other
 plugins, like resolve)
 
 .TP
+.BR charon.plugins.vici.socket " [unix://${piddir}/charon.vici]"
+Socket the vici plugin serves clients.
+
+.TP
 .BR charon.plugins.whitelist.enable " [yes]"
 Enable loaded whitelist plugin.
 
@@ -1397,6 +1308,11 @@ otherwise a random port
 will be allocated.
 
 .TP
+.BR charon.prefer_temporary_addrs " [no]"
+By default public IPv6 addresses are preferred over temporary ones (RFC 4941),
+to make connections more stable. Enable this option to reverse this.
+
+.TP
 .BR charon.process_route " [yes]"
 Process RTM_NEWROUTE and RTM_DELROUTE events.
 
@@ -1480,6 +1396,18 @@ Specific IKEv2 message type to delay, 0 for any.
 Send strongSwan vendor ID payload
 
 .TP
+.B charon.start-scripts
+.br
+Section containing a list of scripts (name = path) that are executed when the
+daemon is started.
+
+.TP
+.B charon.stop-scripts
+.br
+Section containing a list of scripts (name = path) that are executed when the
+daemon is terminated.
+
+.TP
 .B charon.syslog
 .br
 Section to define syslog loggers, see LOGGER CONFIGURATION in
@@ -1567,6 +1495,156 @@ Plugins to load in IMC/IMVs with stand\-alone
 library.
 
 .TP
+.BR libimcv.plugins.imc-attestation.aik_blob " []"
+AIK encrypted private key blob file.
+
+.TP
+.BR libimcv.plugins.imc-attestation.aik_cert " []"
+AIK certificate file.
+
+.TP
+.BR libimcv.plugins.imc-attestation.aik_pubkey " []"
+AIK public key file.
+
+.TP
+.BR libimcv.plugins.imc-attestation.mandatory_dh_groups " [yes]"
+Enforce mandatory Diffie\-Hellman groups.
+
+.TP
+.BR libimcv.plugins.imc-attestation.nonce_len " [20]"
+DH nonce length.
+
+.TP
+.BR libimcv.plugins.imc-attestation.pcr17_after " []"
+Dummy data if the TBOOT log is not retrieved.
+
+.TP
+.BR libimcv.plugins.imc-attestation.pcr17_before " []"
+Dummy data if the TBOOT log is not retrieved.
+
+.TP
+.BR libimcv.plugins.imc-attestation.pcr17_meas " []"
+Dummy data if the TBOOT log is not retrieved.
+
+.TP
+.BR libimcv.plugins.imc-attestation.pcr18_after " []"
+Dummy data if the TBOOT log is not retrieved.
+
+.TP
+.BR libimcv.plugins.imc-attestation.pcr18_before " []"
+Dummy data if the TBOOT log is not retrieved.
+
+.TP
+.BR libimcv.plugins.imc-attestation.pcr18_meas " []"
+Dummy data if the TBOOT log is not retrieved.
+
+.TP
+.BR libimcv.plugins.imc-attestation.pcr_info " [no]"
+Whether to send pcr_before and pcr_after info.
+
+.TP
+.BR libimcv.plugins.imc-attestation.use_quote2 " [yes]"
+Use Quote2 AIK signature instead of Quote signature.
+
+.TP
+.BR libimcv.plugins.imc-os.device_cert " []"
+Manually set the path to the client device certificate (e.g.
+/etc/pts/aikCert.der)
+
+.TP
+.BR libimcv.plugins.imc-os.device_id " []"
+Manually set the client device ID in hexadecimal format (e.g.
+1083f03988c9762703b1c1080c2e46f72b99cc31)
+
+.TP
+.BR libimcv.plugins.imc-os.device_pubkey " []"
+Manually set the path to the client device public key (e.g. /etc/pts/aikPub.der)
+
+.TP
+.BR libimcv.plugins.imc-os.push_info " [yes]"
+Send operating system info without being prompted.
+
+.TP
+.BR libimcv.plugins.imc-scanner.push_info " [yes]"
+Send open listening ports without being prompted.
+
+.TP
+.BR libimcv.plugins.imc-swid.swid_directory " [${prefix}/share]"
+Directory where SWID tags are located.
+
+.TP
+.BR libimcv.plugins.imc-swid.swid_full " [FALSE]"
+Include file information in the XML\-encoded SWID tags.
+
+.TP
+.BR libimcv.plugins.imc-swid.swid_generator " [/usr/local/bin/swid_generator]"
+SWID generator command to be executed.
+
+.TP
+.BR libimcv.plugins.imc-swid.swid_pretty " [FALSE]"
+Generate XML\-encoded SWID tags with pretty indentation.
+
+.TP
+.BR libimcv.plugins.imc-test.additional_ids " [0]"
+Number of additional IMC IDs.
+
+.TP
+.BR libimcv.plugins.imc-test.command " [none]"
+Command to be sent to the Test IMV.
+
+.TP
+.BR libimcv.plugins.imc-test.dummy_size " [0]"
+Size of dummy attribute to be sent to the Test IMV (0 = disabled).
+
+.TP
+.BR libimcv.plugins.imc-test.retry " [no]"
+Do a handshake retry.
+
+.TP
+.BR libimcv.plugins.imc-test.retry_command " []"
+Command to be sent to the Test IMV in the handshake retry.
+
+.TP
+.BR libimcv.plugins.imv-attestation.cadir " []"
+Path to directory with AIK cacerts.
+
+.TP
+.BR libimcv.plugins.imv-attestation.dh_group " [ecp256]"
+Preferred Diffie\-Hellman group.
+
+.TP
+.BR libimcv.plugins.imv-attestation.hash_algorithm " [sha256]"
+Preferred measurement hash algorithm.
+
+.TP
+.BR libimcv.plugins.imv-attestation.mandatory_dh_groups " [yes]"
+Enforce mandatory Diffie\-Hellman groups.
+
+.TP
+.BR libimcv.plugins.imv-attestation.min_nonce_len " [0]"
+DH minimum nonce length.
+
+.TP
+.BR libimcv.plugins.imv-os.remediation_uri " []"
+URI pointing to operating system remediation instructions.
+
+.TP
+.BR libimcv.plugins.imv-scanner.remediation_uri " []"
+URI pointing to scanner remediation instructions.
+
+.TP
+.BR libimcv.plugins.imv-swid.rest_api_timeout " [120]"
+Timeout of SWID REST API HTTP POST transaction.
+
+.TP
+.BR libimcv.plugins.imv-swid.rest_api_uri " []"
+HTTP URI of the SWID REST API.
+
+.TP
+.BR libimcv.plugins.imv-test.rounds " [0]"
+Number of IMC\-IMV retry rounds.
+
+.TP
 .BR libimcv.stderr_quiet " [no]"
 Disable output to stderr with a stand\-alone
 .RI "" "libimcv" ""
@@ -1670,3 +1748,7 @@ Plugins to load in starter.
 .BR starter.load_warning " [yes]"
 Disable charon plugin load option warning.
 
+.TP
+.BR swanctl.load " []"
+Plugins to load in swanctl.
+
diff --git a/config.h.in b/config.h.in
index bfcb4e2..1899b70 100644
--- a/config.h.in
+++ b/config.h.in
@@ -67,8 +67,8 @@
 /* Define to 1 if you have the `funopen' function. */
 #undef HAVE_FUNOPEN
 
-/* have GCC __sync_* atomic operations */
-#undef HAVE_GCC_ATOMIC_OPERATIONS
+/* have GCC __sync_* operations */
+#undef HAVE_GCC_SYNC_OPERATIONS
 
 /* have GCRY_CIPHER_CAMELLIA128 */
 #undef HAVE_GCRY_CIPHER_CAMELLIA
@@ -193,6 +193,9 @@
 /* Define to 1 if you have the `sem_timedwait' function. */
 #undef HAVE_SEM_TIMEDWAIT
 
+/* Define to 1 if you have the `setlinebuf' function. */
+#undef HAVE_SETLINEBUF
+
 /* have sqlite3_prepare_v2() */
 #undef HAVE_SQLITE3_PREPARE_V2
 
@@ -214,6 +217,9 @@
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the `strptime' function. */
+#undef HAVE_STRPTIME
+
 /* Define to 1 if `sadb_x_policy_priority' is a member of `struct
    sadb_x_policy'. */
 #undef HAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY
@@ -221,6 +227,9 @@
 /* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
 #undef HAVE_STRUCT_SOCKADDR_SA_LEN
 
+/* have syslog(3) and friends */
+#undef HAVE_SYSLOG
+
 /* have sys/capability.h */
 #undef HAVE_SYS_CAPABILITY_H
 
@@ -258,9 +267,6 @@
 /* monolithic build embedding plugins */
 #undef MONOLITHIC
 
-/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-#undef NO_MINUS_C_MINUS_O
-
 /* Name of package */
 #undef PACKAGE
 
diff --git a/configure b/configure
index 6c4e4c9..a2004a8 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.1.3.
+# Generated by GNU Autoconf 2.69 for strongSwan 5.2.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.1.3'
-PACKAGE_STRING='strongSwan 5.1.3'
+PACKAGE_VERSION='5.2.0'
+PACKAGE_STRING='strongSwan 5.2.0'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -633,10 +633,18 @@ am__EXEEXT_TRUE
 LTLIBOBJS
 LIBOBJS
 strongswan_options
+USE_SVC_FALSE
+USE_SVC_TRUE
+USE_SWANCTL_FALSE
+USE_SWANCTL_TRUE
+USE_AIKGEN_FALSE
+USE_AIKGEN_TRUE
 USE_CMD_FALSE
 USE_CMD_TRUE
 USE_TKM_FALSE
 USE_TKM_TRUE
+USE_DBGHELP_FALSE
+USE_DBGHELP_TRUE
 COVERAGE_FALSE
 COVERAGE_TRUE
 USE_SILENT_RULES_FALSE
@@ -683,8 +691,10 @@ USE_CONFTEST_FALSE
 USE_CONFTEST_TRUE
 USE_SCRIPTS_FALSE
 USE_SCRIPTS_TRUE
-USE_TOOLS_FALSE
-USE_TOOLS_TRUE
+USE_SCEPCLIENT_FALSE
+USE_SCEPCLIENT_TRUE
+USE_PKI_FALSE
+USE_PKI_TRUE
 USE_NM_FALSE
 USE_NM_TRUE
 USE_CHARON_FALSE
@@ -721,8 +731,6 @@ USE_KERNEL_PFKEY_FALSE
 USE_KERNEL_PFKEY_TRUE
 USE_KERNEL_NETLINK_FALSE
 USE_KERNEL_NETLINK_TRUE
-USE_KERNEL_KLIPS_FALSE
-USE_KERNEL_KLIPS_TRUE
 USE_ATTR_SQL_FALSE
 USE_ATTR_SQL_TRUE
 USE_ATTR_FALSE
@@ -733,6 +741,8 @@ USE_ADDRBLOCK_FALSE
 USE_ADDRBLOCK_TRUE
 USE_FARP_FALSE
 USE_FARP_TRUE
+USE_SOCKET_WIN_FALSE
+USE_SOCKET_WIN_TRUE
 USE_SOCKET_DYNAMIC_FALSE
 USE_SOCKET_DYNAMIC_TRUE
 USE_SOCKET_DEFAULT_FALSE
@@ -835,6 +845,10 @@ USE_LOOKIP_FALSE
 USE_LOOKIP_TRUE
 USE_WHITELIST_FALSE
 USE_WHITELIST_TRUE
+USE_KERNEL_IPH_FALSE
+USE_KERNEL_IPH_TRUE
+USE_KERNEL_WFP_FALSE
+USE_KERNEL_WFP_TRUE
 USE_KERNEL_LIBIPSEC_FALSE
 USE_KERNEL_LIBIPSEC_TRUE
 USE_HA_FALSE
@@ -869,6 +883,8 @@ USE_MEDCLI_FALSE
 USE_MEDCLI_TRUE
 USE_MEDSRV_FALSE
 USE_MEDSRV_TRUE
+USE_VICI_FALSE
+USE_VICI_TRUE
 USE_STROKE_FALSE
 USE_STROKE_TRUE
 USE_NTRU_FALSE
@@ -961,6 +977,8 @@ USE_SOUP_FALSE
 USE_SOUP_TRUE
 USE_UNBOUND_FALSE
 USE_UNBOUND_TRUE
+USE_WINHTTP_FALSE
+USE_WINHTTP_TRUE
 USE_CURL_FALSE
 USE_CURL_TRUE
 USE_TEST_VECTORS_FALSE
@@ -969,6 +987,7 @@ t_plugins
 s_plugins
 h_plugins
 c_plugins
+aikgen_plugins
 cmd_plugins
 nm_plugins
 medsrv_plugins
@@ -998,8 +1017,8 @@ dbusservicedir
 maemo_LIBS
 maemo_CFLAGS
 MYSQLCFLAG
-MYSQLLIB
 MYSQLCONFIG
+MYSQLLIB
 clearsilver_LIBS
 RUBYLIB
 RUBYINCLUDE
@@ -1010,8 +1029,14 @@ xml_LIBS
 xml_CFLAGS
 soup_LIBS
 soup_CFLAGS
-PTHREADLIB
+PLUGIN_CFLAGS
+USE_WINDOWS_FALSE
+USE_WINDOWS_TRUE
+OPENSSL_LIB
 RTLIB
+USE_SYSLOG_FALSE
+USE_SYSLOG_TRUE
+PTHREADLIB
 SOCKLIB
 BTLIB
 DLLIB
@@ -1091,6 +1116,7 @@ ipsec_script
 routing_table_prio
 routing_table
 linux_headers
+swanctldir
 nm_ca_dir
 imcvdir
 plugindir
@@ -1188,6 +1214,7 @@ with_ipseclibdir
 with_plugindir
 with_imcvdir
 with_nm_ca_dir
+with_swanctldir
 with_linux_headers
 with_routing_table
 with_routing_table_prio
@@ -1241,6 +1268,7 @@ enable_curl
 enable_ldap
 enable_soup
 enable_unbound
+enable_winhttp
 enable_mysql
 enable_sqlite
 enable_addrblock
@@ -1279,14 +1307,17 @@ enable_xauth_noauth
 enable_kernel_netlink
 enable_kernel_pfkey
 enable_kernel_pfroute
-enable_kernel_klips
+enable_kernel_iph
 enable_kernel_libipsec
+enable_kernel_wfp
 enable_socket_default
 enable_socket_dynamic
+enable_socket_win
 enable_stroke
 enable_smp
 enable_sql
 enable_uci
+enable_vici
 enable_android_dns
 enable_attr
 enable_attr_sql
@@ -1326,6 +1357,7 @@ enable_systime_fix
 enable_test_vectors
 enable_unit_tester
 enable_updown
+enable_aikgen
 enable_charon
 enable_cmd
 enable_conftest
@@ -1336,10 +1368,14 @@ enable_manager
 enable_medcli
 enable_medsrv
 enable_nm
+enable_pki
+enable_scepclient
 enable_scripts
+enable_svc
+enable_swanctl
 enable_tkm
-enable_tools
 enable_bfd_backtraces
+enable_dbghelp_backtraces
 enable_ikev1
 enable_ikev2
 enable_integrity_test
@@ -1929,7 +1965,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.1.3 to adapt to many kinds of systems.
+\`configure' configures strongSwan 5.2.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1999,7 +2035,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of strongSwan 5.1.3:";;
+     short | recursive ) echo "Configuration of strongSwan 5.2.0:";;
    esac
   cat <<\_ACEOF
 
@@ -2054,6 +2090,7 @@ Optional Features:
   --enable-unbound        enable UNBOUND resolver plugin to perform DNS
                           queries via libunbound. Requires libldns and
                           libunbound.
+  --enable-winhttp        enable WinHTTP based HTTP/HTTPS fetching plugin.
   --enable-mysql          enable MySQL database support. Requires
                           libmysqlclient_r.
   --enable-sqlite         enable SQLite database support. Requires libsqlite3.
@@ -2103,17 +2140,22 @@ Optional Features:
                           disable the netlink kernel interface.
   --enable-kernel-pfkey   enable the PF_KEY kernel interface.
   --enable-kernel-pfroute enable the PF_ROUTE kernel interface.
-  --enable-kernel-klips   enable the KLIPS kernel interface.
+  --enable-kernel-iph     enable the Windows IP Helper based networking
+                          backend.
   --enable-kernel-libipsec
                           enable the libipsec kernel interface.
+  --enable-kernel-wfp     enable the Windows Filtering Platform IPsec backend.
   --disable-socket-default
                           disable default socket implementation for charon.
   --enable-socket-dynamic enable dynamic socket implementation for charon
+  --enable-socket-win     enable Winsock2 based socket implementation for
+                          charon
   --disable-stroke        disable charons stroke configuration backend.
   --enable-smp            enable SMP configuration and control interface.
                           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.
   --enable-android-dns    enable Android specific DNS handler.
   --disable-attr          disable strongswan.conf based configuration
                           attribute plugin.
@@ -2163,6 +2205,7 @@ Optional Features:
   --enable-test-vectors   enable plugin providing crypto test vectors.
   --enable-unit-tester    enable unit tests on IKEv2 daemon startup.
   --disable-updown        disable updown firewall script plugin.
+  --enable-aikgen         enable AIK generator.
   --disable-charon        disable the IKEv1/IKEv2 keying daemon charon.
   --enable-cmd            enable the command line IKE client charon-cmd.
   --enable-conftest       enforce Suite B conformance test framework.
@@ -2176,12 +2219,18 @@ Optional Features:
   --enable-medsrv         enable mediation server web frontend and daemon
                           plugin.
   --enable-nm             enable NetworkManager backend.
+  --disable-pki           disable pki certificate utility.
+  --disable-scepclient    disable SCEP client tool.
   --disable-scripts       disable additional utilities (found in directory
                           scripts).
+  --enable-svc            enable charon Windows service.
+  --enable-swanctl        enable swanctl configuration and control tool.
   --enable-tkm            enable Trusted Key Manager support.
-  --disable-tools         disable additional utilities (scepclient and pki).
   --enable-bfd-backtraces use binutils libbfd to resolve backtraces for memory
                           leaks and segfaults.
+  --enable-dbghelp-backtraces
+                          use dbghlp.dll on Windows to create and print
+                          backtraces for memory leaks and segfaults.
   --disable-ikev1         disable IKEv1 protocol support in charon.
   --disable-ikev2         disable IKEv2 protocol support in charon.
   --enable-integrity-test enable integrity testing of libstrongswan and
@@ -2240,6 +2289,8 @@ Optional Packages:
   --with-nm-ca-dir=arg    directory the NM backend uses to look up trusted
                           root certificates (default:
                           /usr/share/ca-certificates).
+  --with-swanctldir=arg   base directory for swanctl configuration files and
+                          credentials (default: ${sysconfdir}/swanctl).
   --with-linux-headers=arg
                           set directory of linux header files to use (default:
                           \${top_srcdir}/src/include).
@@ -2389,7 +2440,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-strongSwan configure 5.1.3
+strongSwan configure 5.2.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2911,7 +2962,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.1.3, which was
+It was created by strongSwan $as_me 5.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3259,7 +3310,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-am__api_version='1.13'
+am__api_version='1.14'
 
 ac_aux_dir=
 for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@@ -3774,7 +3825,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='strongswan'
- VERSION='5.1.3'
+ VERSION='5.2.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3941,6 +3992,47 @@ $as_echo "$am_cv_prog_tar_ustar" >&6; }
 
 
 
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake at gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
 # Check whether --enable-silent-rules was given.
 if test "${enable_silent_rules+set}" = set; then :
   enableval=$enable_silent_rules;
@@ -4332,6 +4424,18 @@ fi
 
 
 
+# Check whether --with-swanctldir was given.
+if test "${with_swanctldir+set}" = set; then :
+  withval=$with_swanctldir; swanctldir="$withval"
+
+else
+  swanctldir="${sysconfdir}/swanctl"
+
+
+fi
+
+
+
 # Check whether --with-linux-headers was given.
 if test "${with_linux_headers+set}" = set; then :
   withval=$with_linux_headers; linux_headers="$withval"
@@ -5172,6 +5276,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" unbound"
 
+# Check whether --enable-winhttp was given.
+if test "${enable_winhttp+set}" = set; then :
+  enableval=$enable_winhttp; winhttp_given=true
+		if test x$enableval = xyes; then
+			winhttp=true
+		 else
+			winhttp=false
+		fi
+else
+  winhttp=false
+		winhttp_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" winhttp"
+
 # database plugins
 # Check whether --enable-mysql was given.
 if test "${enable_mysql+set}" = set; then :
@@ -5783,21 +5903,21 @@ fi
 
 	disabled_by_default=${disabled_by_default}" kernel_pfroute"
 
-# Check whether --enable-kernel-klips was given.
-if test "${enable_kernel_klips+set}" = set; then :
-  enableval=$enable_kernel_klips; kernel_klips_given=true
+# Check whether --enable-kernel-iph was given.
+if test "${enable_kernel_iph+set}" = set; then :
+  enableval=$enable_kernel_iph; kernel_iph_given=true
 		if test x$enableval = xyes; then
-			kernel_klips=true
+			kernel_iph=true
 		 else
-			kernel_klips=false
+			kernel_iph=false
 		fi
 else
-  kernel_klips=false
-		kernel_klips_given=false
+  kernel_iph=false
+		kernel_iph_given=false
 
 fi
 
-	disabled_by_default=${disabled_by_default}" kernel_klips"
+	disabled_by_default=${disabled_by_default}" kernel_iph"
 
 # Check whether --enable-kernel-libipsec was given.
 if test "${enable_kernel_libipsec+set}" = set; then :
@@ -5815,6 +5935,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" kernel_libipsec"
 
+# Check whether --enable-kernel-wfp was given.
+if test "${enable_kernel_wfp+set}" = set; then :
+  enableval=$enable_kernel_wfp; kernel_wfp_given=true
+		if test x$enableval = xyes; then
+			kernel_wfp=true
+		 else
+			kernel_wfp=false
+		fi
+else
+  kernel_wfp=false
+		kernel_wfp_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" kernel_wfp"
+
 # Check whether --enable-socket-default was given.
 if test "${enable_socket_default+set}" = set; then :
   enableval=$enable_socket_default; socket_default_given=true
@@ -5847,6 +5983,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" socket_dynamic"
 
+# Check whether --enable-socket-win was given.
+if test "${enable_socket_win+set}" = set; then :
+  enableval=$enable_socket_win; socket_win_given=true
+		if test x$enableval = xyes; then
+			socket_win=true
+		 else
+			socket_win=false
+		fi
+else
+  socket_win=false
+		socket_win_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" socket_win"
+
 # configuration/control plugins
 # Check whether --enable-stroke was given.
 if test "${enable_stroke+set}" = set; then :
@@ -5912,6 +6064,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" uci"
 
+# Check whether --enable-vici was given.
+if test "${enable_vici+set}" = set; then :
+  enableval=$enable_vici; vici_given=true
+		if test x$enableval = xyes; then
+			vici=true
+		 else
+			vici=false
+		fi
+else
+  vici=false
+		vici_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" vici"
+
 # attribute provider/consumer plugins
 # Check whether --enable-android-dns was given.
 if test "${enable_android_dns+set}" = set; then :
@@ -6540,6 +6708,22 @@ fi
 	enabled_by_default=${enabled_by_default}" updown"
 
 # programs/components
+# Check whether --enable-aikgen was given.
+if test "${enable_aikgen+set}" = set; then :
+  enableval=$enable_aikgen; aikgen_given=true
+		if test x$enableval = xyes; then
+			aikgen=true
+		 else
+			aikgen=false
+		fi
+else
+  aikgen=false
+		aikgen_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" aikgen"
+
 # Check whether --enable-charon was given.
 if test "${enable_charon+set}" = set; then :
   enableval=$enable_charon; charon_given=true
@@ -6700,6 +6884,38 @@ fi
 
 	disabled_by_default=${disabled_by_default}" nm"
 
+# Check whether --enable-pki was given.
+if test "${enable_pki+set}" = set; then :
+  enableval=$enable_pki; pki_given=true
+		if test x$enableval = xyes; then
+			pki=true
+		 else
+			pki=false
+		fi
+else
+  pki=true
+		pki_given=false
+
+fi
+
+	enabled_by_default=${enabled_by_default}" pki"
+
+# Check whether --enable-scepclient was given.
+if test "${enable_scepclient+set}" = set; then :
+  enableval=$enable_scepclient; scepclient_given=true
+		if test x$enableval = xyes; then
+			scepclient=true
+		 else
+			scepclient=false
+		fi
+else
+  scepclient=true
+		scepclient_given=false
+
+fi
+
+	enabled_by_default=${enabled_by_default}" scepclient"
+
 # Check whether --enable-scripts was given.
 if test "${enable_scripts+set}" = set; then :
   enableval=$enable_scripts; scripts_given=true
@@ -6716,37 +6932,53 @@ fi
 
 	enabled_by_default=${enabled_by_default}" scripts"
 
-# Check whether --enable-tkm was given.
-if test "${enable_tkm+set}" = set; then :
-  enableval=$enable_tkm; tkm_given=true
+# Check whether --enable-svc was given.
+if test "${enable_svc+set}" = set; then :
+  enableval=$enable_svc; svc_given=true
 		if test x$enableval = xyes; then
-			tkm=true
+			svc=true
 		 else
-			tkm=false
+			svc=false
 		fi
 else
-  tkm=false
-		tkm_given=false
+  svc=false
+		svc_given=false
 
 fi
 
-	disabled_by_default=${disabled_by_default}" tkm"
+	disabled_by_default=${disabled_by_default}" svc"
+
+# Check whether --enable-swanctl was given.
+if test "${enable_swanctl+set}" = set; then :
+  enableval=$enable_swanctl; swanctl_given=true
+		if test x$enableval = xyes; then
+			swanctl=true
+		 else
+			swanctl=false
+		fi
+else
+  swanctl=false
+		swanctl_given=false
 
-# Check whether --enable-tools was given.
-if test "${enable_tools+set}" = set; then :
-  enableval=$enable_tools; tools_given=true
+fi
+
+	disabled_by_default=${disabled_by_default}" swanctl"
+
+# Check whether --enable-tkm was given.
+if test "${enable_tkm+set}" = set; then :
+  enableval=$enable_tkm; tkm_given=true
 		if test x$enableval = xyes; then
-			tools=true
+			tkm=true
 		 else
-			tools=false
+			tkm=false
 		fi
 else
-  tools=true
-		tools_given=false
+  tkm=false
+		tkm_given=false
 
 fi
 
-	enabled_by_default=${enabled_by_default}" tools"
+	disabled_by_default=${disabled_by_default}" tkm"
 
 # optional features
 # Check whether --enable-bfd-backtraces was given.
@@ -6765,6 +6997,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" bfd_backtraces"
 
+# Check whether --enable-dbghelp-backtraces was given.
+if test "${enable_dbghelp_backtraces+set}" = set; then :
+  enableval=$enable_dbghelp_backtraces; dbghelp_backtraces_given=true
+		if test x$enableval = xyes; then
+			dbghelp_backtraces=true
+		 else
+			dbghelp_backtraces=false
+		fi
+else
+  dbghelp_backtraces=false
+		dbghelp_backtraces_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" dbghelp_backtraces"
+
 # Check whether --enable-ikev1 was given.
 if test "${enable_ikev1+set}" = set; then :
   enableval=$enable_ikev1; ikev1_given=true
@@ -7778,6 +8026,65 @@ ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
 DEPDIR="${am__leading_dot}deps"
 
 ac_config_commands="$ac_config_commands depfiles"
@@ -7970,131 +8277,6 @@ else
 fi
 
 
-if test "x$CC" != xcc; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
-$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5
-$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
-fi
-set dummy $CC; ac_cc=`$as_echo "$2" |
-		      sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
-if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-# Make sure it works both with $CC and with simple cc.
-# We do the test twice because some compilers refuse to overwrite an
-# existing .o file with -o, though they will create one.
-ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
-rm -f conftest2.*
-if { { case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } &&
-   test -f conftest2.$ac_objext && { { case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; };
-then
-  eval ac_cv_prog_cc_${ac_cc}_c_o=yes
-  if test "x$CC" != xcc; then
-    # Test first that cc exists at all.
-    if { ac_try='cc -c conftest.$ac_ext >&5'
-  { { case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; }; then
-      ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
-      rm -f conftest2.*
-      if { { case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } &&
-	 test -f conftest2.$ac_objext && { { case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; };
-      then
-	# cc works too.
-	:
-      else
-	# cc exists but doesn't like -o.
-	eval ac_cv_prog_cc_${ac_cc}_c_o=no
-      fi
-    fi
-  fi
-else
-  eval ac_cv_prog_cc_${ac_cc}_c_o=no
-fi
-rm -f core conftest*
-
-fi
-if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
-
-fi
-
-# FIXME: we rely on the cache variable name because
-# there is no other way.
-set dummy $CC
-am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
-eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
-if test "$am_t" != yes; then
-   # Losing compiler, so override with the script.
-   # FIXME: It is wrong to rewrite CC.
-   # But if we don't then we get into trouble of one sort or another.
-   # A longer-term fix would be to have automake use am__CC in this case,
-   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
-   CC="$am_aux_dir/compile $CC"
-fi
-
 
 
 # Make sure we can run config.sub.
@@ -16780,6 +16962,10 @@ if test x$fips_prf = xtrue; then
 	fi
 fi
 
+if test x$swanctl = xtrue; then
+	vici=true
+fi
+
 if test x$smp = xtrue -o x$tnccs_11 = xtrue -o x$tnc_ifmap = xtrue; then
 	xml=true
 fi
@@ -17421,11 +17607,11 @@ fi
 
 
 
-# FreeBSD has clock_gettime in libc, Linux needs librt
+# Android has pthread_* functions in bionic (libc), others need libpthread
 LIBS=""
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
-$as_echo_n "checking for library containing clock_gettime... " >&6; }
-if ${ac_cv_search_clock_gettime+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
+$as_echo_n "checking for library containing pthread_create... " >&6; }
+if ${ac_cv_search_pthread_create+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
@@ -17438,16 +17624,16 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char clock_gettime ();
+char pthread_create ();
 int
 main ()
 {
-return clock_gettime ();
+return pthread_create ();
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' rt; do
+for ac_lib in '' pthread; do
   if test -z "$ac_lib"; then
     ac_res="none required"
   else
@@ -17455,86 +17641,15 @@ for ac_lib in '' rt; do
     LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
   fi
   if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_clock_gettime=$ac_res
+  ac_cv_search_pthread_create=$ac_res
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext
-  if ${ac_cv_search_clock_gettime+:} false; then :
+  if ${ac_cv_search_pthread_create+:} false; then :
   break
 fi
 done
-if ${ac_cv_search_clock_gettime+:} false; then :
-
-else
-  ac_cv_search_clock_gettime=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
-$as_echo "$ac_cv_search_clock_gettime" >&6; }
-ac_res=$ac_cv_search_clock_gettime
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-  RTLIB=$LIBS
-fi
-
-for ac_func in clock_gettime
-do :
-  ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
-if test "x$ac_cv_func_clock_gettime" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_CLOCK_GETTIME 1
-_ACEOF
-
-fi
-done
-
-
-
-# Android has pthread_* functions in bionic (libc), others need libpthread
-LIBS=""
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
-$as_echo_n "checking for library containing pthread_create... " >&6; }
-if ${ac_cv_search_pthread_create+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pthread_create ();
-int
-main ()
-{
-return pthread_create ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' pthread; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_pthread_create=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_pthread_create+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_pthread_create+:} false; then :
+if ${ac_cv_search_pthread_create+:} false; then :
 
 else
   ac_cv_search_pthread_create=no
@@ -17830,7 +17945,7 @@ _ACEOF
 fi
 done
 
-for ac_func in fmemopen funopen mmap memrchr
+for ac_func in fmemopen funopen mmap memrchr setlinebuf strptime
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -17843,6 +17958,25 @@ fi
 done
 
 
+ac_fn_c_check_func "$LINENO" "syslog" "ac_cv_func_syslog"
+if test "x$ac_cv_func_syslog" = xyes; then :
+
+
+$as_echo "#define HAVE_SYSLOG /**/" >>confdefs.h
+
+	syslog=true
+
+fi
+
+ if test "x$syslog" = xtrue; then
+  USE_SYSLOG_TRUE=
+  USE_SYSLOG_FALSE='#'
+else
+  USE_SYSLOG_TRUE='#'
+  USE_SYSLOG_FALSE=
+fi
+
+
 for ac_header in sys/sockio.h glob.h net/if_tun.h linux/fib_rules.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -17931,7 +18065,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 int
 main ()
 {
-struct in6_addr in6;
+struct in6_addr in6 __attribute__((unused));
 		  in6 = in6addr_any;
   ;
   return 0;
@@ -18082,8 +18216,8 @@ $as_echo "no" >&6; }
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc atomic operations" >&5
-$as_echo_n "checking for gcc atomic operations... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC __sync operations" >&5
+$as_echo_n "checking for GCC __sync operations... " >&6; }
 if test "$cross_compiling" = yes; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -18093,10 +18227,9 @@ else
 /* end confdefs.h.  */
 
 			int main() {
-			volatile int ref = 1;
+			int ref = 1;
 			__sync_fetch_and_add (&ref, 1);
 			__sync_sub_and_fetch (&ref, 1);
-			/* Make sure test fails if operations are not supported */
 			__sync_val_compare_and_swap(&ref, 1, 0);
 			return ref;
 		}
@@ -18106,7 +18239,7 @@ if ac_fn_c_try_run "$LINENO"; then :
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; };
 
-$as_echo "#define HAVE_GCC_ATOMIC_OPERATIONS /**/" >>confdefs.h
+$as_echo "#define HAVE_GCC_SYNC_OPERATIONS /**/" >>confdefs.h
 
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
@@ -18160,6 +18293,196 @@ fi
 
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows target" >&5
+$as_echo_n "checking for Windows target... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <windows.h>
+int
+main ()
+{
+#ifndef WIN32
+		  # error WIN32 undefined
+		  #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+		windows=true
+		openssl_lib=eay32
+		PTHREADLIB=""
+
+		# explicitly disable ms-bitfields, as it breaks __attribute__((packed))
+		case "$CFLAGS" in
+			*ms-bitfields*) ;;
+			*) CFLAGS="$CFLAGS -mno-ms-bitfields" ;;
+		esac
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		openssl_lib=crypto
+
+		# check for clock_gettime() on non-Windows only. Otherwise this
+		# check might find clock_gettime() in libwinpthread, but we don't want
+		# to link against it.
+		saved_LIBS=$LIBS
+		# FreeBSD has clock_gettime in libc, Linux needs librt
+		LIBS=""
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
+$as_echo_n "checking for library containing clock_gettime... " >&6; }
+if ${ac_cv_search_clock_gettime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' rt; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_clock_gettime=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_clock_gettime+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_clock_gettime+:} false; then :
+
+else
+  ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
+$as_echo "$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  RTLIB=$LIBS
+fi
+
+		for ac_func in clock_gettime
+do :
+  ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
+if test "x$ac_cv_func_clock_gettime" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CLOCK_GETTIME 1
+_ACEOF
+
+fi
+done
+
+
+		LIBS=$saved_LIBS
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+OPENSSL_LIB=-l$openssl_lib
+
+ if test "x$windows" = xtrue; then
+  USE_WINDOWS_TRUE=
+  USE_WINDOWS_FALSE='#'
+else
+  USE_WINDOWS_TRUE='#'
+  USE_WINDOWS_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working __attribute__((packed))" >&5
+$as_echo_n "checking for working __attribute__((packed))... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+		struct test { char a; short b; } __attribute__((packed));
+		char x[sizeof(struct test) == sizeof(char) + sizeof(short) ? 1 : -1]
+			__attribute__((unused));
+		return 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }; as_fn_error $? "__attribute__((packed)) does not work" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking clang" >&5
+$as_echo_n "checking clang... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+		 #ifndef __clang__
+		 # error not using LLVM clang
+		 #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		# GCC, but not MinGW requires -rdynamic for plugins
+		if test x$windows != xtrue; then
+			PLUGIN_CFLAGS=-rdynamic
+
+		fi
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
 if test x$printf_hooks = xvstr; then
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lvstr" >&5
 $as_echo_n "checking for main in -lvstr... " >&6; }
@@ -18774,6 +19097,53 @@ $as_echo "#define TSS_TROUSERS /**/" >>confdefs.h
 
 fi
 
+if test x$imv_swid = xtrue; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ljson" >&5
+$as_echo_n "checking for main in -ljson... " >&6; }
+if ${ac_cv_lib_json_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljson  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_json_main=yes
+else
+  ac_cv_lib_json_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_json_main" >&5
+$as_echo "$ac_cv_lib_json_main" >&6; }
+if test "x$ac_cv_lib_json_main" = xyes; then :
+  LIBS="$LIBS"
+else
+  as_fn_error $? "JSON library libjson not found" "$LINENO" 5
+fi
+
+	ac_fn_c_check_header_mongrel "$LINENO" "json/json.h" "ac_cv_header_json_json_h" "$ac_includes_default"
+if test "x$ac_cv_header_json_json_h" = xyes; then :
+
+else
+  as_fn_error $? "JSON header json/json.h not found!" "$LINENO" 5
+fi
+
+
+fi
+
 if test x$dumm = xtrue; then
 
 pkg_failed=no
@@ -19135,7 +19505,55 @@ fi
 fi
 
 if test x$mysql = xtrue; then
-	# Extract the first word of "mysql_config", so it can be a program name with args.
+	if test "x$windows" = xtrue; then
+		ac_fn_c_check_header_mongrel "$LINENO" "mysql.h" "ac_cv_header_mysql_h" "$ac_includes_default"
+if test "x$ac_cv_header_mysql_h" = xyes; then :
+
+else
+  as_fn_error $? "MySQL header file mysql.h not found!" "$LINENO" 5
+fi
+
+
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lmysql" >&5
+$as_echo_n "checking for main in -lmysql... " >&6; }
+if ${ac_cv_lib_mysql_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmysql  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_mysql_main=yes
+else
+  ac_cv_lib_mysql_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysql_main" >&5
+$as_echo "$ac_cv_lib_mysql_main" >&6; }
+if test "x$ac_cv_lib_mysql_main" = xyes; then :
+  LIBS="$LIBS"
+else
+  as_fn_error $? "MySQL library not found!" "$LINENO" 5
+fi
+
+		MYSQLLIB=-lmysql
+
+	else
+		# Extract the first word of "mysql_config", so it can be a program name with args.
 set dummy mysql_config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
@@ -19176,13 +19594,14 @@ $as_echo "no" >&6; }
 fi
 
 
-	if test x$MYSQLCONFIG = x; then
-		as_fn_error $? "mysql_config not found!" "$LINENO" 5
-	fi
-	MYSQLLIB=`$MYSQLCONFIG --libs_r`
+		if test x$MYSQLCONFIG = x; then
+			as_fn_error $? "mysql_config not found!" "$LINENO" 5
+		fi
+		MYSQLLIB=`$MYSQLCONFIG --libs_r`
 
-	MYSQLCFLAG=`$MYSQLCONFIG --cflags`
+		MYSQLCFLAG=`$MYSQLCONFIG --cflags`
 
+	fi
 fi
 
 if test x$sqlite = xtrue; then
@@ -19283,13 +19702,14 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
 if test x$openssl = xtrue; then
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lcrypto" >&5
-$as_echo_n "checking for main in -lcrypto... " >&6; }
-if ${ac_cv_lib_crypto_main+:} false; then :
+	as_ac_Lib=`$as_echo "ac_cv_lib_$openssl_lib''_main" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$openssl_lib" >&5
+$as_echo_n "checking for main in -l$openssl_lib... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypto  $LIBS"
+LIBS="-l$openssl_lib  $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -19303,20 +19723,21 @@ return main ();
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_crypto_main=yes
+  eval "$as_ac_Lib=yes"
 else
-  ac_cv_lib_crypto_main=no
+  eval "$as_ac_Lib=no"
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_main" >&5
-$as_echo "$ac_cv_lib_crypto_main" >&6; }
-if test "x$ac_cv_lib_crypto_main" = xyes; then :
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
   LIBS="$LIBS"
 else
-  as_fn_error $? "OpenSSL crypto library not found" "$LINENO" 5
+  as_fn_error $? "OpenSSL lib$openssl_lib not found" "$LINENO" 5
 fi
 
 	ac_fn_c_check_header_mongrel "$LINENO" "openssl/evp.h" "ac_cv_header_openssl_evp_h" "$ac_includes_default"
@@ -20354,6 +20775,7 @@ manager_plugins=
 medsrv_plugins=
 nm_plugins=
 cmd_plugins=
+aikgen_plugins=
 
 # location specific lists for checksumming,
 # for src/libcharon, src/libhydra, src/libstrongswan and src/libtnccs
@@ -20374,15 +20796,25 @@ if test x$curl = xtrue; then
 		s_plugins=${s_plugins}" curl"
 		charon_plugins=${charon_plugins}" curl"
 		scepclient_plugins=${scepclient_plugins}" curl"
+		pki_plugins=${pki_plugins}" curl"
 		scripts_plugins=${scripts_plugins}" curl"
 		nm_plugins=${nm_plugins}" curl"
 		cmd_plugins=${cmd_plugins}" curl"
 
 	fi
 
+if test x$winhttp = xtrue; then
+		s_plugins=${s_plugins}" winhttp"
+		charon_plugins=${charon_plugins}" winhttp"
+		pki_plugins=${pki_plugins}" winhttp"
+		scripts_plugins=${scripts_plugins}" winhttp"
+
+	fi
+
 if test x$soup = xtrue; then
 		s_plugins=${s_plugins}" soup"
 		charon_plugins=${charon_plugins}" soup"
+		pki_plugins=${pki_plugins}" soup"
 		scripts_plugins=${scripts_plugins}" soup"
 		nm_plugins=${nm_plugins}" soup"
 		cmd_plugins=${cmd_plugins}" soup"
@@ -20489,6 +20921,7 @@ if test x$sha1 = xtrue; then
 		attest_plugins=${attest_plugins}" sha1"
 		nm_plugins=${nm_plugins}" sha1"
 		cmd_plugins=${cmd_plugins}" sha1"
+		aikgen_plugins=${aikgen_plugins}" sha1"
 
 	fi
 
@@ -20502,6 +20935,7 @@ if test x$sha2 = xtrue; then
 		attest_plugins=${attest_plugins}" sha2"
 		nm_plugins=${nm_plugins}" sha2"
 		cmd_plugins=${cmd_plugins}" sha2"
+		aikgen_plugins=${aikgen_plugins}" sha2"
 
 	fi
 
@@ -20525,6 +20959,7 @@ if test x$md5 = xtrue; then
 		attest_plugins=${attest_plugins}" md5"
 		nm_plugins=${nm_plugins}" md5"
 		cmd_plugins=${cmd_plugins}" md5"
+		aikgen_plugins=${aikgen_plugins}" md5"
 
 	fi
 
@@ -20538,6 +20973,7 @@ if test x$rdrand = xtrue; then
 		attest_plugins=${attest_plugins}" rdrand"
 		nm_plugins=${nm_plugins}" rdrand"
 		cmd_plugins=${cmd_plugins}" rdrand"
+		aikgen_plugins=${aikgen_plugins}" rdrand"
 
 	fi
 
@@ -20551,6 +20987,7 @@ if test x$random = xtrue; then
 		attest_plugins=${attest_plugins}" random"
 		nm_plugins=${nm_plugins}" random"
 		cmd_plugins=${cmd_plugins}" random"
+		aikgen_plugins=${aikgen_plugins}" random"
 
 	fi
 
@@ -20559,6 +20996,7 @@ if test x$nonce = xtrue; then
 		charon_plugins=${charon_plugins}" nonce"
 		nm_plugins=${nm_plugins}" nonce"
 		cmd_plugins=${cmd_plugins}" nonce"
+		aikgen_plugins=${aikgen_plugins}" nonce"
 
 	fi
 
@@ -20571,12 +21009,14 @@ if test x$x509 = xtrue; then
 		attest_plugins=${attest_plugins}" x509"
 		nm_plugins=${nm_plugins}" x509"
 		cmd_plugins=${cmd_plugins}" x509"
+		aikgen_plugins=${aikgen_plugins}" x509"
 
 	fi
 
 if test x$revocation = xtrue; then
 		s_plugins=${s_plugins}" revocation"
 		charon_plugins=${charon_plugins}" revocation"
+		pki_plugins=${pki_plugins}" revocation"
 		nm_plugins=${nm_plugins}" revocation"
 		cmd_plugins=${cmd_plugins}" revocation"
 
@@ -20600,6 +21040,7 @@ if test x$pubkey = xtrue; then
 		s_plugins=${s_plugins}" pubkey"
 		charon_plugins=${charon_plugins}" pubkey"
 		cmd_plugins=${cmd_plugins}" pubkey"
+		aikgen_plugins=${aikgen_plugins}" pubkey"
 
 	fi
 
@@ -20614,6 +21055,7 @@ if test x$pkcs1 = xtrue; then
 		attest_plugins=${attest_plugins}" pkcs1"
 		nm_plugins=${nm_plugins}" pkcs1"
 		cmd_plugins=${cmd_plugins}" pkcs1"
+		aikgen_plugins=${aikgen_plugins}" pkcs1"
 
 	fi
 
@@ -20697,6 +21139,7 @@ if test x$pem = xtrue; then
 		attest_plugins=${attest_plugins}" pem"
 		nm_plugins=${nm_plugins}" pem"
 		cmd_plugins=${cmd_plugins}" pem"
+		aikgen_plugins=${aikgen_plugins}" pem"
 
 	fi
 
@@ -20717,6 +21160,7 @@ if test x$openssl = xtrue; then
 		attest_plugins=${attest_plugins}" openssl"
 		nm_plugins=${nm_plugins}" openssl"
 		cmd_plugins=${cmd_plugins}" openssl"
+		aikgen_plugins=${aikgen_plugins}" openssl"
 
 	fi
 
@@ -20731,6 +21175,7 @@ if test x$gcrypt = xtrue; then
 		attest_plugins=${attest_plugins}" gcrypt"
 		nm_plugins=${nm_plugins}" gcrypt"
 		cmd_plugins=${cmd_plugins}" gcrypt"
+		aikgen_plugins=${aikgen_plugins}" gcrypt"
 
 	fi
 
@@ -20744,6 +21189,7 @@ if test x$af_alg = xtrue; then
 		attest_plugins=${attest_plugins}" af-alg"
 		nm_plugins=${nm_plugins}" af-alg"
 		cmd_plugins=${cmd_plugins}" af-alg"
+		aikgen_plugins=${aikgen_plugins}" af-alg"
 
 	fi
 
@@ -20766,6 +21212,7 @@ if test x$gmp = xtrue; then
 		attest_plugins=${attest_plugins}" gmp"
 		nm_plugins=${nm_plugins}" gmp"
 		cmd_plugins=${cmd_plugins}" gmp"
+		aikgen_plugins=${aikgen_plugins}" gmp"
 
 	fi
 
@@ -20870,6 +21317,18 @@ if test x$kernel_libipsec = xtrue; then
 
 	fi
 
+if test x$kernel_wfp = xtrue; then
+		c_plugins=${c_plugins}" kernel-wfp"
+		charon_plugins=${charon_plugins}" kernel-wfp"
+
+	fi
+
+if test x$kernel_iph = xtrue; then
+		c_plugins=${c_plugins}" kernel-iph"
+		charon_plugins=${charon_plugins}" kernel-iph"
+
+	fi
+
 if test x$kernel_pfkey = xtrue; then
 		h_plugins=${h_plugins}" kernel-pfkey"
 		charon_plugins=${charon_plugins}" kernel-pfkey"
@@ -20888,13 +21347,6 @@ if test x$kernel_pfroute = xtrue; then
 
 	fi
 
-if test x$kernel_klips = xtrue; then
-		h_plugins=${h_plugins}" kernel-klips"
-		charon_plugins=${charon_plugins}" kernel-klips"
-		starter_plugins=${starter_plugins}" kernel-klips"
-
-	fi
-
 if test x$kernel_netlink = xtrue; then
 		h_plugins=${h_plugins}" kernel-netlink"
 		charon_plugins=${charon_plugins}" kernel-netlink"
@@ -20926,6 +21378,12 @@ if test x$socket_dynamic = xtrue; then
 
 	fi
 
+if test x$socket_win = xtrue; then
+		c_plugins=${c_plugins}" socket-win"
+		charon_plugins=${charon_plugins}" socket-win"
+
+	fi
+
 if test x$farp = xtrue; then
 		c_plugins=${c_plugins}" farp"
 		charon_plugins=${charon_plugins}" farp"
@@ -20938,6 +21396,12 @@ if test x$stroke = xtrue; then
 
 	fi
 
+if test x$vici = xtrue; then
+		c_plugins=${c_plugins}" vici"
+		charon_plugins=${charon_plugins}" vici"
+
+	fi
+
 if test x$smp = xtrue; then
 		c_plugins=${c_plugins}" smp"
 		charon_plugins=${charon_plugins}" smp"
@@ -21296,6 +21760,7 @@ if test x$unit_tester = xtrue; then
 
 
 
+
 # ======================
 #  set Makefile.am vars
 # ======================
@@ -21318,6 +21783,14 @@ else
   USE_CURL_FALSE=
 fi
 
+ if test x$winhttp = xtrue; then
+  USE_WINHTTP_TRUE=
+  USE_WINHTTP_FALSE='#'
+else
+  USE_WINHTTP_TRUE='#'
+  USE_WINHTTP_FALSE=
+fi
+
  if test x$unbound = xtrue; then
   USE_UNBOUND_TRUE=
   USE_UNBOUND_FALSE='#'
@@ -21689,6 +22162,14 @@ else
   USE_STROKE_FALSE=
 fi
 
+ if test x$vici = xtrue; then
+  USE_VICI_TRUE=
+  USE_VICI_FALSE='#'
+else
+  USE_VICI_TRUE='#'
+  USE_VICI_FALSE=
+fi
+
  if test x$medsrv = xtrue; then
   USE_MEDSRV_TRUE=
   USE_MEDSRV_FALSE='#'
@@ -21825,6 +22306,22 @@ else
   USE_KERNEL_LIBIPSEC_FALSE=
 fi
 
+ if test x$kernel_wfp = xtrue; then
+  USE_KERNEL_WFP_TRUE=
+  USE_KERNEL_WFP_FALSE='#'
+else
+  USE_KERNEL_WFP_TRUE='#'
+  USE_KERNEL_WFP_FALSE=
+fi
+
+ if test x$kernel_iph = xtrue; then
+  USE_KERNEL_IPH_TRUE=
+  USE_KERNEL_IPH_FALSE='#'
+else
+  USE_KERNEL_IPH_TRUE='#'
+  USE_KERNEL_IPH_FALSE=
+fi
+
  if test x$whitelist = xtrue; then
   USE_WHITELIST_TRUE=
   USE_WHITELIST_FALSE='#'
@@ -22233,6 +22730,14 @@ else
   USE_SOCKET_DYNAMIC_FALSE=
 fi
 
+ if test x$socket_win = xtrue; then
+  USE_SOCKET_WIN_TRUE=
+  USE_SOCKET_WIN_FALSE='#'
+else
+  USE_SOCKET_WIN_TRUE='#'
+  USE_SOCKET_WIN_FALSE=
+fi
+
  if test x$farp = xtrue; then
   USE_FARP_TRUE=
   USE_FARP_FALSE='#'
@@ -22276,14 +22781,6 @@ else
   USE_ATTR_SQL_FALSE=
 fi
 
- if test x$kernel_klips = xtrue; then
-  USE_KERNEL_KLIPS_TRUE=
-  USE_KERNEL_KLIPS_FALSE='#'
-else
-  USE_KERNEL_KLIPS_TRUE='#'
-  USE_KERNEL_KLIPS_FALSE=
-fi
-
  if test x$kernel_netlink = xtrue; then
   USE_KERNEL_NETLINK_TRUE=
   USE_KERNEL_NETLINK_FALSE='#'
@@ -22431,12 +22928,20 @@ else
   USE_NM_FALSE=
 fi
 
- if test x$tools = xtrue; then
-  USE_TOOLS_TRUE=
-  USE_TOOLS_FALSE='#'
+ if test x$pki = xtrue; then
+  USE_PKI_TRUE=
+  USE_PKI_FALSE='#'
+else
+  USE_PKI_TRUE='#'
+  USE_PKI_FALSE=
+fi
+
+ if test x$scepclient = xtrue; then
+  USE_SCEPCLIENT_TRUE=
+  USE_SCEPCLIENT_FALSE='#'
 else
-  USE_TOOLS_TRUE='#'
-  USE_TOOLS_FALSE=
+  USE_SCEPCLIENT_TRUE='#'
+  USE_SCEPCLIENT_FALSE=
 fi
 
  if test x$scripts = xtrue; then
@@ -22455,7 +22960,7 @@ else
   USE_CONFTEST_FALSE=
 fi
 
- if test x$charon = xtrue -o x$tools = 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; then
+ if 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; then
   USE_LIBSTRONGSWAN_TRUE=
   USE_LIBSTRONGSWAN_FALSE='#'
 else
@@ -22463,7 +22968,7 @@ else
   USE_LIBSTRONGSWAN_FALSE=
 fi
 
- if test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue; then
+ if test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = xtrue; then
   USE_LIBHYDRA_TRUE=
   USE_LIBHYDRA_FALSE='#'
 else
@@ -22471,7 +22976,7 @@ else
   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; then
+ 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; then
   USE_LIBCHARON_TRUE=
   USE_LIBCHARON_FALSE='#'
 else
@@ -22519,7 +23024,7 @@ else
   USE_FILE_CONFIG_FALSE=
 fi
 
- if test x$stroke = xtrue -o x$tools = xtrue -o x$conftest = xtrue; then
+ if test x$stroke = xtrue -o x$scepclient = xtrue -o x$conftest = xtrue; then
   USE_IPSEC_SCRIPT_TRUE=
   USE_IPSEC_SCRIPT_FALSE='#'
 else
@@ -22591,7 +23096,7 @@ else
   USE_PTS_FALSE=
 fi
 
- if test x$tss = xtrousers; then
+ if test x$tss = xtrousers -o x$aikgen = xtrue; then
   USE_TROUSERS_TRUE=
   USE_TROUSERS_FALSE='#'
 else
@@ -22623,6 +23128,14 @@ else
   COVERAGE_FALSE=
 fi
 
+ if test x$dbghelp_backtraces = xtrue; then
+  USE_DBGHELP_TRUE=
+  USE_DBGHELP_FALSE='#'
+else
+  USE_DBGHELP_TRUE='#'
+  USE_DBGHELP_FALSE=
+fi
+
  if test x$tkm = xtrue; then
   USE_TKM_TRUE=
   USE_TKM_FALSE='#'
@@ -22639,6 +23152,30 @@ else
   USE_CMD_FALSE=
 fi
 
+ if test x$aikgen = xtrue; then
+  USE_AIKGEN_TRUE=
+  USE_AIKGEN_FALSE='#'
+else
+  USE_AIKGEN_TRUE='#'
+  USE_AIKGEN_FALSE=
+fi
+
+ if test x$swanctl = xtrue; then
+  USE_SWANCTL_TRUE=
+  USE_SWANCTL_FALSE='#'
+else
+  USE_SWANCTL_TRUE='#'
+  USE_SWANCTL_FALSE=
+fi
+
+ if test x$svc = xtrue; then
+  USE_SVC_TRUE=
+  USE_SVC_FALSE='#'
+else
+  USE_SVC_TRUE='#'
+  USE_SVC_FALSE=
+fi
+
 
 # ========================
 #  set global definitions
@@ -22676,6 +23213,9 @@ fi
 
 strongswan_options=
 
+if test -z "$USE_AIKGEN_TRUE"; then :
+  strongswan_options=${strongswan_options}" aikgen"
+fi
 if test -z "$USE_ATTR_SQL_TRUE"; then :
   strongswan_options=${strongswan_options}" pool"
 fi
@@ -22703,8 +23243,14 @@ fi
 if test -z "$USE_MEDSRV_TRUE"; then :
   strongswan_options=${strongswan_options}" medsrv"
 fi
-if test -z "$USE_TOOLS_TRUE"; then :
-  strongswan_options=${strongswan_options}" tools"
+if test -z "$USE_SCEPCLIENT_TRUE"; then :
+  strongswan_options=${strongswan_options}" scepclient"
+fi
+if test -z "$USE_PKI_TRUE"; then :
+  strongswan_options=${strongswan_options}" pki"
+fi
+if test -z "$USE_SWANCTL_TRUE"; then :
+  strongswan_options=${strongswan_options}" swanctl"
 fi
 
 
@@ -22713,14 +23259,14 @@ fi
 #  build Makefiles
 # =================
 
-ac_config_files="$ac_config_files Makefile conf/Makefile man/Makefile init/Makefile init/systemd/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/libstrongswan/plugins/sha1/Makefile src/li [...]
+ac_config_files="$ac_config_files Makefile conf/Makefile man/Makefile init/Makefile init/systemd/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/libstrongswan/plugins/sha1/Makefile src/li [...]
 
 
 # =================
 #  build man pages
 # =================
 
-ac_config_files="$ac_config_files conf/strongswan.conf.5.head conf/strongswan.conf.5.tail man/ipsec.conf.5 man/ipsec.secrets.5 src/charon-cmd/charon-cmd.8 src/pki/man/pki.1 src/pki/man/pki---gen.1 src/pki/man/pki---issue.1 src/pki/man/pki---keyid.1 src/pki/man/pki---pkcs7.1 src/pki/man/pki---print.1 src/pki/man/pki---pub.1 src/pki/man/pki---req.1 src/pki/man/pki---self.1 src/pki/man/pki---signcrl.1 src/pki/man/pki---acert.1 src/pki/man/pki---verify.1"
+ac_config_files="$ac_config_files conf/strongswan.conf.5.head conf/strongswan.conf.5.tail man/ipsec.conf.5 man/ipsec.secrets.5 src/charon-cmd/charon-cmd.8 src/pki/man/pki.1 src/pki/man/pki---gen.1 src/pki/man/pki---issue.1 src/pki/man/pki---keyid.1 src/pki/man/pki---pkcs7.1 src/pki/man/pki---print.1 src/pki/man/pki---pub.1 src/pki/man/pki---req.1 src/pki/man/pki---self.1 src/pki/man/pki---signcrl.1 src/pki/man/pki---acert.1 src/pki/man/pki---verify.1 src/swanctl/swanctl.8 src/swanctl/swa [...]
 
 
 cat >confcache <<\_ACEOF
@@ -22861,6 +23407,14 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 
+if test -z "${USE_SYSLOG_TRUE}" && test -z "${USE_SYSLOG_FALSE}"; then
+  as_fn_error $? "conditional \"USE_SYSLOG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_WINDOWS_TRUE}" && test -z "${USE_WINDOWS_FALSE}"; then
+  as_fn_error $? "conditional \"USE_WINDOWS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_DEV_HEADERS_TRUE}" && test -z "${USE_DEV_HEADERS_FALSE}"; then
   as_fn_error $? "conditional \"USE_DEV_HEADERS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -22873,6 +23427,10 @@ if test -z "${USE_CURL_TRUE}" && test -z "${USE_CURL_FALSE}"; then
   as_fn_error $? "conditional \"USE_CURL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_WINHTTP_TRUE}" && test -z "${USE_WINHTTP_FALSE}"; then
+  as_fn_error $? "conditional \"USE_WINHTTP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_UNBOUND_TRUE}" && test -z "${USE_UNBOUND_FALSE}"; then
   as_fn_error $? "conditional \"USE_UNBOUND\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -23057,6 +23615,10 @@ if test -z "${USE_STROKE_TRUE}" && test -z "${USE_STROKE_FALSE}"; then
   as_fn_error $? "conditional \"USE_STROKE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_VICI_TRUE}" && test -z "${USE_VICI_FALSE}"; then
+  as_fn_error $? "conditional \"USE_VICI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_MEDSRV_TRUE}" && test -z "${USE_MEDSRV_FALSE}"; then
   as_fn_error $? "conditional \"USE_MEDSRV\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -23125,6 +23687,14 @@ if test -z "${USE_KERNEL_LIBIPSEC_TRUE}" && test -z "${USE_KERNEL_LIBIPSEC_FALSE
   as_fn_error $? "conditional \"USE_KERNEL_LIBIPSEC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_KERNEL_WFP_TRUE}" && test -z "${USE_KERNEL_WFP_FALSE}"; then
+  as_fn_error $? "conditional \"USE_KERNEL_WFP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_KERNEL_IPH_TRUE}" && test -z "${USE_KERNEL_IPH_FALSE}"; then
+  as_fn_error $? "conditional \"USE_KERNEL_IPH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_WHITELIST_TRUE}" && test -z "${USE_WHITELIST_FALSE}"; then
   as_fn_error $? "conditional \"USE_WHITELIST\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -23329,6 +23899,10 @@ if test -z "${USE_SOCKET_DYNAMIC_TRUE}" && test -z "${USE_SOCKET_DYNAMIC_FALSE}"
   as_fn_error $? "conditional \"USE_SOCKET_DYNAMIC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_SOCKET_WIN_TRUE}" && test -z "${USE_SOCKET_WIN_FALSE}"; then
+  as_fn_error $? "conditional \"USE_SOCKET_WIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_FARP_TRUE}" && test -z "${USE_FARP_FALSE}"; then
   as_fn_error $? "conditional \"USE_FARP\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -23349,10 +23923,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_KLIPS_TRUE}" && test -z "${USE_KERNEL_KLIPS_FALSE}"; then
-  as_fn_error $? "conditional \"USE_KERNEL_KLIPS\" 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
@@ -23425,8 +23995,12 @@ if test -z "${USE_NM_TRUE}" && test -z "${USE_NM_FALSE}"; then
   as_fn_error $? "conditional \"USE_NM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_TOOLS_TRUE}" && test -z "${USE_TOOLS_FALSE}"; then
-  as_fn_error $? "conditional \"USE_TOOLS\" was never defined.
+if test -z "${USE_PKI_TRUE}" && test -z "${USE_PKI_FALSE}"; then
+  as_fn_error $? "conditional \"USE_PKI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_SCEPCLIENT_TRUE}" && test -z "${USE_SCEPCLIENT_FALSE}"; then
+  as_fn_error $? "conditional \"USE_SCEPCLIENT\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 if test -z "${USE_SCRIPTS_TRUE}" && test -z "${USE_SCRIPTS_FALSE}"; then
@@ -23521,6 +24095,10 @@ if test -z "${COVERAGE_TRUE}" && test -z "${COVERAGE_FALSE}"; then
   as_fn_error $? "conditional \"COVERAGE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_DBGHELP_TRUE}" && test -z "${USE_DBGHELP_FALSE}"; then
+  as_fn_error $? "conditional \"USE_DBGHELP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_TKM_TRUE}" && test -z "${USE_TKM_FALSE}"; then
   as_fn_error $? "conditional \"USE_TKM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -23529,6 +24107,18 @@ if test -z "${USE_CMD_TRUE}" && test -z "${USE_CMD_FALSE}"; then
   as_fn_error $? "conditional \"USE_CMD\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_AIKGEN_TRUE}" && test -z "${USE_AIKGEN_FALSE}"; then
+  as_fn_error $? "conditional \"USE_AIKGEN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_SWANCTL_TRUE}" && test -z "${USE_SWANCTL_FALSE}"; then
+  as_fn_error $? "conditional \"USE_SWANCTL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${USE_SVC_TRUE}" && test -z "${USE_SVC_FALSE}"; then
+  as_fn_error $? "conditional \"USE_SVC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 
 : "${CONFIG_STATUS=./config.status}"
 ac_write_fail=0
@@ -23926,7 +24516,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.1.3, which was
+This file was extended by strongSwan $as_me 5.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23992,7 +24582,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.1.3
+strongSwan config.status 5.2.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -24439,6 +25029,7 @@ do
     "src/libstrongswan/plugins/sshkey/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/sshkey/Makefile" ;;
     "src/libstrongswan/plugins/pem/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/pem/Makefile" ;;
     "src/libstrongswan/plugins/curl/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/curl/Makefile" ;;
+    "src/libstrongswan/plugins/winhttp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/winhttp/Makefile" ;;
     "src/libstrongswan/plugins/unbound/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/unbound/Makefile" ;;
     "src/libstrongswan/plugins/soup/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/soup/Makefile" ;;
     "src/libstrongswan/plugins/ldap/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/ldap/Makefile" ;;
@@ -24460,7 +25051,6 @@ do
     "src/libhydra/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/Makefile" ;;
     "src/libhydra/plugins/attr/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/plugins/attr/Makefile" ;;
     "src/libhydra/plugins/attr_sql/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/plugins/attr_sql/Makefile" ;;
-    "src/libhydra/plugins/kernel_klips/Makefile") CONFIG_FILES="$CONFIG_FILES src/libhydra/plugins/kernel_klips/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" ;;
@@ -24495,6 +25085,7 @@ do
     "src/charon-nm/Makefile") CONFIG_FILES="$CONFIG_FILES src/charon-nm/Makefile" ;;
     "src/charon-tkm/Makefile") CONFIG_FILES="$CONFIG_FILES src/charon-tkm/Makefile" ;;
     "src/charon-cmd/Makefile") CONFIG_FILES="$CONFIG_FILES src/charon-cmd/Makefile" ;;
+    "src/charon-svc/Makefile") CONFIG_FILES="$CONFIG_FILES src/charon-svc/Makefile" ;;
     "src/libcharon/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/Makefile" ;;
     "src/libcharon/plugins/eap_aka/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/eap_aka/Makefile" ;;
     "src/libcharon/plugins/eap_aka_3gpp2/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/eap_aka_3gpp2/Makefile" ;;
@@ -24522,6 +25113,7 @@ do
     "src/libcharon/plugins/tnc_pdp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/tnc_pdp/Makefile" ;;
     "src/libcharon/plugins/socket_default/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/socket_default/Makefile" ;;
     "src/libcharon/plugins/socket_dynamic/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/socket_dynamic/Makefile" ;;
+    "src/libcharon/plugins/socket_win/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/socket_win/Makefile" ;;
     "src/libcharon/plugins/farp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/farp/Makefile" ;;
     "src/libcharon/plugins/smp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/smp/Makefile" ;;
     "src/libcharon/plugins/sql/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/sql/Makefile" ;;
@@ -24534,6 +25126,8 @@ do
     "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_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" ;;
     "src/libcharon/plugins/whitelist/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/whitelist/Makefile" ;;
     "src/libcharon/plugins/lookip/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/lookip/Makefile" ;;
     "src/libcharon/plugins/error_notify/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/error_notify/Makefile" ;;
@@ -24548,6 +25142,7 @@ do
     "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/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" ;;
     "src/libcharon/plugins/unit_tester/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcharon/plugins/unit_tester/Makefile" ;;
@@ -24555,10 +25150,12 @@ do
     "src/stroke/Makefile") CONFIG_FILES="$CONFIG_FILES src/stroke/Makefile" ;;
     "src/ipsec/Makefile") CONFIG_FILES="$CONFIG_FILES src/ipsec/Makefile" ;;
     "src/starter/Makefile") CONFIG_FILES="$CONFIG_FILES src/starter/Makefile" ;;
+    "src/starter/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/starter/tests/Makefile" ;;
     "src/_updown/Makefile") CONFIG_FILES="$CONFIG_FILES src/_updown/Makefile" ;;
     "src/_updown_espmark/Makefile") CONFIG_FILES="$CONFIG_FILES src/_updown_espmark/Makefile" ;;
     "src/_copyright/Makefile") CONFIG_FILES="$CONFIG_FILES src/_copyright/Makefile" ;;
     "src/scepclient/Makefile") CONFIG_FILES="$CONFIG_FILES src/scepclient/Makefile" ;;
+    "src/aikgen/Makefile") CONFIG_FILES="$CONFIG_FILES src/aikgen/Makefile" ;;
     "src/pki/Makefile") CONFIG_FILES="$CONFIG_FILES src/pki/Makefile" ;;
     "src/pki/man/Makefile") CONFIG_FILES="$CONFIG_FILES src/pki/man/Makefile" ;;
     "src/pool/Makefile") CONFIG_FILES="$CONFIG_FILES src/pool/Makefile" ;;
@@ -24570,6 +25167,7 @@ do
     "src/checksum/Makefile") CONFIG_FILES="$CONFIG_FILES src/checksum/Makefile" ;;
     "src/conftest/Makefile") CONFIG_FILES="$CONFIG_FILES src/conftest/Makefile" ;;
     "src/pt-tls-client/Makefile") CONFIG_FILES="$CONFIG_FILES src/pt-tls-client/Makefile" ;;
+    "src/swanctl/Makefile") CONFIG_FILES="$CONFIG_FILES src/swanctl/Makefile" ;;
     "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
     "testing/Makefile") CONFIG_FILES="$CONFIG_FILES testing/Makefile" ;;
     "conf/strongswan.conf.5.head") CONFIG_FILES="$CONFIG_FILES conf/strongswan.conf.5.head" ;;
@@ -24589,6 +25187,9 @@ do
     "src/pki/man/pki---signcrl.1") CONFIG_FILES="$CONFIG_FILES src/pki/man/pki---signcrl.1" ;;
     "src/pki/man/pki---acert.1") CONFIG_FILES="$CONFIG_FILES src/pki/man/pki---acert.1" ;;
     "src/pki/man/pki---verify.1") CONFIG_FILES="$CONFIG_FILES src/pki/man/pki---verify.1" ;;
+    "src/swanctl/swanctl.8") CONFIG_FILES="$CONFIG_FILES src/swanctl/swanctl.8" ;;
+    "src/swanctl/swanctl.conf.5.head") CONFIG_FILES="$CONFIG_FILES src/swanctl/swanctl.conf.5.head" ;;
+    "src/swanctl/swanctl.conf.5.tail") CONFIG_FILES="$CONFIG_FILES src/swanctl/swanctl.conf.5.tail" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
diff --git a/configure.ac b/configure.ac
index 2ad372b..8f4d763 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@
 #  initialize & set some vars
 # ============================
 
-AC_INIT([strongSwan],[5.1.3])
+AC_INIT([strongSwan],[5.2.0])
 AM_INIT_AUTOMAKE(m4_esyscmd([
 	echo tar-ustar
 	echo subdir-objects
@@ -56,6 +56,7 @@ ARG_WITH_SUBST([ipseclibdir],        [${libdir%/}/ipsec], [set installation path
 ARG_WITH_SUBST([plugindir],          [${ipseclibdir%/}/plugins], [set the installation path of plugins])
 ARG_WITH_SUBST([imcvdir],            [${ipseclibdir%/}/imcvs], [set the installation path of IMC and IMV dynamic librariers])
 ARG_WITH_SUBST([nm-ca-dir],          [/usr/share/ca-certificates], [directory the NM backend uses to look up trusted root certificates])
+ARG_WITH_SUBST([swanctldir],         [${sysconfdir}/swanctl], [base directory for swanctl configuration files and credentials])
 ARG_WITH_SUBST([linux-headers],      [\${top_srcdir}/src/include], [set directory of linux header files to use])
 ARG_WITH_SUBST([routing-table],      [220], [set routing table to use for IPsec routes])
 ARG_WITH_SUBST([routing-table-prio], [220], [set priority for IPsec routing table])
@@ -160,6 +161,7 @@ ARG_ENABL_SET([curl],           [enable CURL fetcher plugin to fetch files via l
 ARG_ENABL_SET([ldap],           [enable LDAP fetching plugin to fetch files via libldap. Requires openLDAP.])
 ARG_ENABL_SET([soup],           [enable soup fetcher plugin to fetch from HTTP via libsoup. Requires libsoup.])
 ARG_ENABL_SET([unbound],        [enable UNBOUND resolver plugin to perform DNS queries via libunbound. Requires libldns and libunbound.])
+ARG_ENABL_SET([winhttp],        [enable WinHTTP based HTTP/HTTPS fetching plugin.])
 # database plugins
 ARG_ENABL_SET([mysql],          [enable MySQL database support. Requires libmysqlclient_r.])
 ARG_ENABL_SET([sqlite],         [enable SQLite database support. Requires libsqlite3.])
@@ -201,15 +203,18 @@ ARG_ENABL_SET([xauth-noauth],   [enable XAuth pseudo-backend that does not actua
 ARG_DISBL_SET([kernel-netlink], [disable the netlink kernel interface.])
 ARG_ENABL_SET([kernel-pfkey],   [enable the PF_KEY kernel interface.])
 ARG_ENABL_SET([kernel-pfroute], [enable the PF_ROUTE kernel interface.])
-ARG_ENABL_SET([kernel-klips],   [enable the KLIPS kernel interface.])
+ARG_ENABL_SET([kernel-iph],     [enable the Windows IP Helper based networking backend.])
 ARG_ENABL_SET([kernel-libipsec],[enable the libipsec kernel interface.])
+ARG_ENABL_SET([kernel-wfp],     [enable the Windows Filtering Platform IPsec backend.])
 ARG_DISBL_SET([socket-default], [disable default socket implementation for charon.])
 ARG_ENABL_SET([socket-dynamic], [enable dynamic socket implementation for charon])
+ARG_ENABL_SET([socket-win],     [enable Winsock2 based socket implementation for charon])
 # configuration/control plugins
 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.])
 # 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.])
@@ -253,6 +258,7 @@ ARG_ENABL_SET([test-vectors],   [enable plugin providing crypto test vectors.])
 ARG_ENABL_SET([unit-tester],    [enable unit tests on IKEv2 daemon startup.])
 ARG_DISBL_SET([updown],         [disable updown firewall script plugin.])
 # programs/components
+ARG_ENABL_SET([aikgen],         [enable AIK generator.])
 ARG_DISBL_SET([charon],         [disable the IKEv1/IKEv2 keying daemon charon.])
 ARG_ENABL_SET([cmd],            [enable the command line IKE client charon-cmd.])
 ARG_ENABL_SET([conftest],       [enforce Suite B conformance test framework.])
@@ -263,11 +269,15 @@ ARG_ENABL_SET([manager],        [enable web management console (proof of concept
 ARG_ENABL_SET([medcli],         [enable mediation client configuration database plugin.])
 ARG_ENABL_SET([medsrv],         [enable mediation server web frontend and daemon plugin.])
 ARG_ENABL_SET([nm],             [enable NetworkManager backend.])
+ARG_DISBL_SET([pki],            [disable pki certificate utility.])
+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([swanctl],        [enable swanctl configuration and control tool.])
 ARG_ENABL_SET([tkm],            [enable Trusted Key Manager support.])
-ARG_DISBL_SET([tools],          [disable additional utilities (scepclient and pki).])
 # optional features
 ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.])
+ARG_ENABL_SET([dbghelp-backtraces],[use dbghlp.dll on Windows to create and print backtraces for memory leaks and segfaults.])
 ARG_DISBL_SET([ikev1],          [disable IKEv1 protocol support in charon.])
 ARG_DISBL_SET([ikev2],          [disable IKEv2 protocol support in charon.])
 ARG_ENABL_SET([integrity-test], [enable integrity testing of libstrongswan and plugins.])
@@ -397,6 +407,10 @@ if test x$fips_prf = xtrue; then
 	fi
 fi
 
+if test x$swanctl = xtrue; then
+	vici=true
+fi
+
 if test x$smp = xtrue -o x$tnccs_11 = xtrue -o x$tnc_ifmap = xtrue; then
 	xml=true
 fi
@@ -444,12 +458,6 @@ AC_SEARCH_LIBS(socket, socket, [SOCKLIB=$LIBS],
 )
 AC_SUBST(SOCKLIB)
 
-# FreeBSD has clock_gettime in libc, Linux needs librt
-LIBS=""
-AC_SEARCH_LIBS(clock_gettime, rt, [RTLIB=$LIBS])
-AC_CHECK_FUNCS(clock_gettime)
-AC_SUBST(RTLIB)
-
 # Android has pthread_* functions in bionic (libc), others need libpthread
 LIBS=""
 AC_SEARCH_LIBS(pthread_create, pthread, [PTHREADLIB=$LIBS])
@@ -559,7 +567,13 @@ AC_CHECK_FUNC(
 )
 
 AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r)
-AC_CHECK_FUNCS(fmemopen funopen mmap memrchr)
+AC_CHECK_FUNCS(fmemopen funopen mmap memrchr setlinebuf strptime)
+
+AC_CHECK_FUNC([syslog], [
+	AC_DEFINE([HAVE_SYSLOG], [], [have syslog(3) and friends])
+	syslog=true
+])
+AM_CONDITIONAL(USE_SYSLOG, [test "x$syslog" = xtrue])
 
 AC_CHECK_HEADERS(sys/sockio.h glob.h net/if_tun.h linux/fib_rules.h)
 AC_CHECK_HEADERS(net/pfkeyv2.h netipsec/ipsec.h netinet6/ipsec.h linux/udp.h)
@@ -592,7 +606,7 @@ AC_COMPILE_IFELSE(
 		[[#include <sys/types.h>
 		  #include <sys/socket.h>
 		  #include <netinet/in.h>]],
-		[[struct in6_addr in6;
+		[[struct in6_addr in6 __attribute__((unused));
 		  in6 = in6addr_any;]])],
 	[AC_MSG_RESULT([yes]);
 	 AC_DEFINE([HAVE_IN6ADDR_ANY], [], [have struct in6_addr in6addr_any])],
@@ -667,21 +681,20 @@ AC_COMPILE_IFELSE(
 	[AC_MSG_RESULT([no])]
 )
 
-AC_MSG_CHECKING([for gcc atomic operations])
+AC_MSG_CHECKING([for GCC __sync operations])
 AC_RUN_IFELSE([AC_LANG_SOURCE(
 	[[
 			int main() {
-			volatile int ref = 1;
+			int ref = 1;
 			__sync_fetch_and_add (&ref, 1);
 			__sync_sub_and_fetch (&ref, 1);
-			/* Make sure test fails if operations are not supported */
 			__sync_val_compare_and_swap(&ref, 1, 0);
 			return ref;
 		}
 	]])],
 	[AC_MSG_RESULT([yes]);
-	 AC_DEFINE([HAVE_GCC_ATOMIC_OPERATIONS], [],
-		   [have GCC __sync_* atomic operations])],
+	 AC_DEFINE([HAVE_GCC_SYNC_OPERATIONS], [],
+		   [have GCC __sync_* operations])],
 	[AC_MSG_RESULT([no])],
 	[AC_MSG_RESULT([no])]
 )
@@ -717,6 +730,76 @@ if test x$printf_hooks = xauto -o x$printf_hooks = xglibc; then
 	)
 fi
 
+AC_MSG_CHECKING([for Windows target])
+AC_COMPILE_IFELSE(
+	[AC_LANG_PROGRAM(
+		[[#include <windows.h>]],
+		[[#ifndef WIN32
+		  # error WIN32 undefined
+		  #endif
+		]])],
+	[
+		AC_MSG_RESULT([yes])
+		windows=true
+		openssl_lib=eay32
+		AC_SUBST(PTHREADLIB, "")
+		# explicitly disable ms-bitfields, as it breaks __attribute__((packed))
+		case "$CFLAGS" in
+			*ms-bitfields*) ;;
+			*) CFLAGS="$CFLAGS -mno-ms-bitfields" ;;
+		esac
+	],
+	[
+		AC_MSG_RESULT([no])
+		openssl_lib=crypto
+
+		# check for clock_gettime() on non-Windows only. Otherwise this
+		# check might find clock_gettime() in libwinpthread, but we don't want
+		# to link against it.
+		saved_LIBS=$LIBS
+		# FreeBSD has clock_gettime in libc, Linux needs librt
+		LIBS=""
+		AC_SEARCH_LIBS(clock_gettime, rt, [RTLIB=$LIBS])
+		AC_CHECK_FUNCS(clock_gettime)
+		AC_SUBST(RTLIB)
+		LIBS=$saved_LIBS
+	]
+)
+AC_SUBST(OPENSSL_LIB, [-l$openssl_lib])
+AM_CONDITIONAL(USE_WINDOWS, [test "x$windows" = xtrue])
+
+AC_MSG_CHECKING([for working __attribute__((packed))])
+AC_COMPILE_IFELSE(
+	[AC_LANG_PROGRAM([], [[
+		struct test { char a; short b; } __attribute__((packed));
+		char x[sizeof(struct test) == sizeof(char) + sizeof(short) ? 1 : -1]
+			__attribute__((unused));
+		return 0;
+	]])],
+	[AC_MSG_RESULT([yes])],
+	[AC_MSG_RESULT([no]); AC_MSG_ERROR([__attribute__((packed)) does not work])]
+)
+
+AC_MSG_CHECKING([clang])
+AC_COMPILE_IFELSE(
+	[AC_LANG_PROGRAM(
+		[], [[
+		 #ifndef __clang__
+		 # error not using LLVM clang
+		 #endif
+		]])],
+	[
+		AC_MSG_RESULT([yes])
+	],
+	[
+		AC_MSG_RESULT([no])
+		# GCC, but not MinGW requires -rdynamic for plugins
+		if test x$windows != xtrue; then
+			AC_SUBST(PLUGIN_CFLAGS, [-rdynamic])
+		fi
+	]
+)
+
 if test x$printf_hooks = xvstr; then
 	AC_CHECK_LIB([vstr],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([Vstr string library not found])],[])
 	AC_DEFINE([USE_VSTR], [], [use Vstr string library for printf hooks])
@@ -792,6 +875,11 @@ if test x$tss = xtrousers; then
 	AC_DEFINE([TSS_TROUSERS], [], [use TrouSerS library libtspi as TSS implementation])
 fi
 
+if test x$imv_swid = xtrue; then
+	AC_CHECK_LIB([json],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([JSON library libjson not found])],[])
+	AC_CHECK_HEADER([json/json.h],,[AC_MSG_ERROR([JSON header json/json.h not found!])])
+fi
+
 if test x$dumm = xtrue; then
 	PKG_CHECK_MODULES(gtk, [gtk+-2.0 vte])
 	AC_SUBST(gtk_CFLAGS)
@@ -858,12 +946,18 @@ if test x$fast = xtrue; then
 fi
 
 if test x$mysql = xtrue; then
-	AC_PATH_PROG([MYSQLCONFIG], [mysql_config], [], [$PATH:/bin:/usr/bin:/usr/local/bin])
-	if test x$MYSQLCONFIG = x; then
-		AC_MSG_ERROR([mysql_config not found!])
+	if test "x$windows" = xtrue; then
+		AC_CHECK_HEADER([mysql.h],,[AC_MSG_ERROR([MySQL header file mysql.h not found!])])
+		AC_CHECK_LIB([mysql],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([MySQL library not found!])],[])
+		AC_SUBST(MYSQLLIB, -lmysql)
+	else
+		AC_PATH_PROG([MYSQLCONFIG], [mysql_config], [], [$PATH:/bin:/usr/bin:/usr/local/bin])
+		if test x$MYSQLCONFIG = x; then
+			AC_MSG_ERROR([mysql_config not found!])
+		fi
+		AC_SUBST(MYSQLLIB, `$MYSQLCONFIG --libs_r`)
+		AC_SUBST(MYSQLCFLAG, `$MYSQLCONFIG --cflags`)
 	fi
-	AC_SUBST(MYSQLLIB, `$MYSQLCONFIG --libs_r`)
-	AC_SUBST(MYSQLCFLAG, `$MYSQLCONFIG --cflags`)
 fi
 
 if test x$sqlite = xtrue; then
@@ -892,7 +986,7 @@ if test x$sqlite = xtrue; then
 fi
 
 if test x$openssl = xtrue; then
-	AC_CHECK_LIB([crypto],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([OpenSSL crypto library not found])],[])
+	AC_CHECK_LIB([$openssl_lib],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([OpenSSL lib$openssl_lib not found])],[])
 	AC_CHECK_HEADER([openssl/evp.h],,[AC_MSG_ERROR([OpenSSL header openssl/evp.h not found!])])
 fi
 
@@ -1060,6 +1154,7 @@ manager_plugins=
 medsrv_plugins=
 nm_plugins=
 cmd_plugins=
+aikgen_plugins=
 
 # location specific lists for checksumming,
 # for src/libcharon, src/libhydra, src/libstrongswan and src/libtnccs
@@ -1069,8 +1164,9 @@ s_plugins=
 t_plugins=
 
 ADD_PLUGIN([test-vectors],         [s charon scepclient pki])
-ADD_PLUGIN([curl],                 [s charon scepclient scripts nm cmd])
-ADD_PLUGIN([soup],                 [s charon scripts nm cmd])
+ADD_PLUGIN([curl],                 [s charon scepclient pki scripts nm cmd])
+ADD_PLUGIN([winhttp],              [s charon pki scripts])
+ADD_PLUGIN([soup],                 [s charon pki scripts nm cmd])
 ADD_PLUGIN([unbound],              [s charon scripts])
 ADD_PLUGIN([ldap],                 [s charon scepclient scripts nm cmd])
 ADD_PLUGIN([mysql],                [s charon pool manager medsrv attest])
@@ -1080,19 +1176,19 @@ 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 medsrv attest nm cmd])
-ADD_PLUGIN([sha2],                 [s charon scepclient pki scripts medsrv attest nm cmd])
+ADD_PLUGIN([sha1],                 [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
+ADD_PLUGIN([sha2],                 [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
 ADD_PLUGIN([md4],                  [s charon manager scepclient pki nm cmd])
-ADD_PLUGIN([md5],                  [s charon scepclient pki scripts attest nm cmd])
-ADD_PLUGIN([rdrand],               [s charon scepclient pki scripts medsrv attest nm cmd])
-ADD_PLUGIN([random],               [s charon scepclient pki scripts medsrv attest nm cmd])
-ADD_PLUGIN([nonce],                [s charon nm cmd])
-ADD_PLUGIN([x509],                 [s charon scepclient pki scripts attest nm cmd])
-ADD_PLUGIN([revocation],           [s charon 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])
+ADD_PLUGIN([random],               [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
+ADD_PLUGIN([nonce],                [s charon nm cmd aikgen])
+ADD_PLUGIN([x509],                 [s charon scepclient pki scripts attest nm cmd aikgen])
+ADD_PLUGIN([revocation],           [s charon pki nm cmd])
 ADD_PLUGIN([constraints],          [s charon nm cmd])
 ADD_PLUGIN([acert],                [s charon])
-ADD_PLUGIN([pubkey],               [s charon cmd])
-ADD_PLUGIN([pkcs1],                [s charon scepclient pki scripts manager medsrv attest nm cmd])
+ADD_PLUGIN([pubkey],               [s charon cmd aikgen])
+ADD_PLUGIN([pkcs1],                [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
 ADD_PLUGIN([pkcs7],                [s charon scepclient pki scripts nm cmd])
 ADD_PLUGIN([pkcs8],                [s charon scepclient pki scripts manager medsrv attest nm cmd])
 ADD_PLUGIN([pkcs12],               [s charon scepclient pki scripts cmd])
@@ -1101,13 +1197,13 @@ ADD_PLUGIN([dnskey],               [s charon pki])
 ADD_PLUGIN([sshkey],               [s charon pki nm cmd])
 ADD_PLUGIN([dnscert],              [c charon])
 ADD_PLUGIN([ipseckey],             [c charon])
-ADD_PLUGIN([pem],                  [s charon scepclient pki scripts manager medsrv attest nm cmd])
+ADD_PLUGIN([pem],                  [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
 ADD_PLUGIN([padlock],              [s charon])
-ADD_PLUGIN([openssl],              [s charon scepclient pki scripts manager medsrv attest nm cmd])
-ADD_PLUGIN([gcrypt],               [s charon scepclient pki scripts manager medsrv attest nm cmd])
-ADD_PLUGIN([af-alg],               [s charon scepclient pki scripts medsrv attest nm cmd])
+ADD_PLUGIN([openssl],              [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
+ADD_PLUGIN([gcrypt],               [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
+ADD_PLUGIN([af-alg],               [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
 ADD_PLUGIN([fips-prf],             [s charon nm cmd])
-ADD_PLUGIN([gmp],                  [s charon scepclient pki scripts manager medsrv attest nm cmd])
+ADD_PLUGIN([gmp],                  [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
 ADD_PLUGIN([agent],                [s charon nm cmd])
 ADD_PLUGIN([keychain],             [s charon cmd])
 ADD_PLUGIN([xcbc],                 [s charon nm cmd])
@@ -1121,15 +1217,18 @@ ADD_PLUGIN([attr],                 [h charon])
 ADD_PLUGIN([attr-sql],             [h charon])
 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-klips],         [h charon starter])
 ADD_PLUGIN([kernel-netlink],       [h charon starter nm cmd])
 ADD_PLUGIN([resolve],              [h charon cmd])
 ADD_PLUGIN([socket-default],       [c charon nm cmd])
 ADD_PLUGIN([socket-dynamic],       [c charon cmd])
+ADD_PLUGIN([socket-win],           [c charon])
 ADD_PLUGIN([farp],                 [c charon])
 ADD_PLUGIN([stroke],               [c charon])
+ADD_PLUGIN([vici],                 [c charon])
 ADD_PLUGIN([smp],                  [c charon])
 ADD_PLUGIN([sql],                  [c charon])
 ADD_PLUGIN([updown],               [c charon])
@@ -1196,6 +1295,7 @@ AC_SUBST(manager_plugins)
 AC_SUBST(medsrv_plugins)
 AC_SUBST(nm_plugins)
 AC_SUBST(cmd_plugins)
+AC_SUBST(aikgen_plugins)
 
 AC_SUBST(c_plugins)
 AC_SUBST(h_plugins)
@@ -1210,6 +1310,7 @@ AC_SUBST(t_plugins)
 # -----------------------
 AM_CONDITIONAL(USE_TEST_VECTORS, test x$test_vectors = xtrue)
 AM_CONDITIONAL(USE_CURL, test x$curl = xtrue)
+AM_CONDITIONAL(USE_WINHTTP, test x$winhttp = xtrue)
 AM_CONDITIONAL(USE_UNBOUND, test x$unbound = xtrue)
 AM_CONDITIONAL(USE_SOUP, test x$soup = xtrue)
 AM_CONDITIONAL(USE_LDAP, test x$ldap = xtrue)
@@ -1259,6 +1360,7 @@ AM_CONDITIONAL(USE_NTRU, test x$ntru = xtrue)
 #  charon plugins
 # ----------------
 AM_CONDITIONAL(USE_STROKE, test x$stroke = xtrue)
+AM_CONDITIONAL(USE_VICI, test x$vici = xtrue)
 AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue)
 AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue)
 AM_CONDITIONAL(USE_UCI, test x$uci = xtrue)
@@ -1276,6 +1378,8 @@ AM_CONDITIONAL(USE_UNIT_TESTS, test x$unit_tester = xtrue)
 AM_CONDITIONAL(USE_LOAD_TESTER, test x$load_tester = xtrue)
 AM_CONDITIONAL(USE_HA, test x$ha = 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)
 AM_CONDITIONAL(USE_WHITELIST, test x$whitelist = xtrue)
 AM_CONDITIONAL(USE_LOOKIP, test x$lookip = xtrue)
 AM_CONDITIONAL(USE_ERROR_NOTIFY, test x$error_notify = xtrue)
@@ -1327,6 +1431,7 @@ AM_CONDITIONAL(USE_IMC_SWID, test x$imc_swid = xtrue)
 AM_CONDITIONAL(USE_IMV_SWID, test x$imv_swid = xtrue)
 AM_CONDITIONAL(USE_SOCKET_DEFAULT, test x$socket_default = xtrue)
 AM_CONDITIONAL(USE_SOCKET_DYNAMIC, test x$socket_dynamic = xtrue)
+AM_CONDITIONAL(USE_SOCKET_WIN, test x$socket_win = xtrue)
 AM_CONDITIONAL(USE_FARP, test x$farp = xtrue)
 AM_CONDITIONAL(USE_ADDRBLOCK, test x$addrblock = xtrue)
 AM_CONDITIONAL(USE_UNITY, test x$unity = xtrue)
@@ -1335,7 +1440,6 @@ AM_CONDITIONAL(USE_UNITY, test x$unity = xtrue)
 # ---------------
 AM_CONDITIONAL(USE_ATTR, test x$attr = xtrue)
 AM_CONDITIONAL(USE_ATTR_SQL, test x$attr_sql = xtrue)
-AM_CONDITIONAL(USE_KERNEL_KLIPS, test x$kernel_klips = 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)
@@ -1357,18 +1461,19 @@ AM_CONDITIONAL(USE_THREADS, test x$threads = xtrue)
 AM_CONDITIONAL(USE_ADNS, test x$adns = xtrue)
 AM_CONDITIONAL(USE_CHARON, test x$charon = xtrue)
 AM_CONDITIONAL(USE_NM, test x$nm = xtrue)
-AM_CONDITIONAL(USE_TOOLS, test x$tools = xtrue)
+AM_CONDITIONAL(USE_PKI, test x$pki = xtrue)
+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$tools = 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)
-AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = 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)
+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)
+AM_CONDITIONAL(USE_LIBHYDRA, test x$charon = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = 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)
 AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue)
 AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue)
 AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue)
 AM_CONDITIONAL(USE_LIBPTTLS, test x$tnc_tnccs = xtrue)
 AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue)
-AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$stroke = xtrue -o x$tools = xtrue -o x$conftest = xtrue)
+AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$stroke = xtrue -o x$scepclient = xtrue -o x$conftest = xtrue)
 AM_CONDITIONAL(USE_LIBCAP, test x$capabilities = xlibcap)
 AM_CONDITIONAL(USE_VSTR, test x$printf_hooks = xvstr)
 AM_CONDITIONAL(USE_BUILTIN_PRINTF, test x$printf_hooks = xbuiltin)
@@ -1377,12 +1482,16 @@ AM_CONDITIONAL(USE_TLS, test x$tls = xtrue)
 AM_CONDITIONAL(USE_RADIUS, test x$radius = xtrue)
 AM_CONDITIONAL(USE_IMCV, test x$imcv = xtrue)
 AM_CONDITIONAL(USE_PTS, test x$pts = xtrue)
-AM_CONDITIONAL(USE_TROUSERS, test x$tss = xtrousers)
+AM_CONDITIONAL(USE_TROUSERS, test x$tss = xtrousers -o x$aikgen = xtrue)
 AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue)
 AM_CONDITIONAL(USE_SILENT_RULES, test x$enable_silent_rules = xyes)
 AM_CONDITIONAL(COVERAGE, test x$coverage = xtrue)
+AM_CONDITIONAL(USE_DBGHELP, test x$dbghelp_backtraces = xtrue)
 AM_CONDITIONAL(USE_TKM, test x$tkm = xtrue)
 AM_CONDITIONAL(USE_CMD, test x$cmd = xtrue)
+AM_CONDITIONAL(USE_AIKGEN, test x$aikgen = xtrue)
+AM_CONDITIONAL(USE_SWANCTL, test x$swanctl = xtrue)
+AM_CONDITIONAL(USE_SVC, test x$svc = xtrue)
 
 # ========================
 #  set global definitions
@@ -1410,6 +1519,7 @@ fi
 
 strongswan_options=
 
+AM_COND_IF([USE_AIKGEN], [strongswan_options=${strongswan_options}" aikgen"])
 AM_COND_IF([USE_ATTR_SQL], [strongswan_options=${strongswan_options}" pool"])
 AM_COND_IF([USE_CHARON], [strongswan_options=${strongswan_options}" charon charon-logging"])
 AM_COND_IF([USE_FILE_CONFIG], [strongswan_options=${strongswan_options}" starter"])
@@ -1419,7 +1529,9 @@ AM_COND_IF([USE_IMV_OS], [strongswan_options=${strongswan_options}" pacman"])
 AM_COND_IF([USE_LIBTNCCS], [strongswan_options=${strongswan_options}" tnc"])
 AM_COND_IF([USE_MANAGER], [strongswan_options=${strongswan_options}" manager"])
 AM_COND_IF([USE_MEDSRV], [strongswan_options=${strongswan_options}" medsrv"])
-AM_COND_IF([USE_TOOLS], [strongswan_options=${strongswan_options}" tools"])
+AM_COND_IF([USE_SCEPCLIENT], [strongswan_options=${strongswan_options}" scepclient"])
+AM_COND_IF([USE_PKI], [strongswan_options=${strongswan_options}" pki"])
+AM_COND_IF([USE_SWANCTL], [strongswan_options=${strongswan_options}" swanctl"])
 
 AC_SUBST(strongswan_options)
 
@@ -1466,6 +1578,7 @@ AC_CONFIG_FILES([
 	src/libstrongswan/plugins/sshkey/Makefile
 	src/libstrongswan/plugins/pem/Makefile
 	src/libstrongswan/plugins/curl/Makefile
+	src/libstrongswan/plugins/winhttp/Makefile
 	src/libstrongswan/plugins/unbound/Makefile
 	src/libstrongswan/plugins/soup/Makefile
 	src/libstrongswan/plugins/ldap/Makefile
@@ -1487,7 +1600,6 @@ AC_CONFIG_FILES([
 	src/libhydra/Makefile
 	src/libhydra/plugins/attr/Makefile
 	src/libhydra/plugins/attr_sql/Makefile
-	src/libhydra/plugins/kernel_klips/Makefile
 	src/libhydra/plugins/kernel_netlink/Makefile
 	src/libhydra/plugins/kernel_pfkey/Makefile
 	src/libhydra/plugins/kernel_pfroute/Makefile
@@ -1522,6 +1634,7 @@ AC_CONFIG_FILES([
 	src/charon-nm/Makefile
 	src/charon-tkm/Makefile
 	src/charon-cmd/Makefile
+	src/charon-svc/Makefile
 	src/libcharon/Makefile
 	src/libcharon/plugins/eap_aka/Makefile
 	src/libcharon/plugins/eap_aka_3gpp2/Makefile
@@ -1549,6 +1662,7 @@ AC_CONFIG_FILES([
 	src/libcharon/plugins/tnc_pdp/Makefile
 	src/libcharon/plugins/socket_default/Makefile
 	src/libcharon/plugins/socket_dynamic/Makefile
+	src/libcharon/plugins/socket_win/Makefile
 	src/libcharon/plugins/farp/Makefile
 	src/libcharon/plugins/smp/Makefile
 	src/libcharon/plugins/sql/Makefile
@@ -1561,6 +1675,8 @@ AC_CONFIG_FILES([
 	src/libcharon/plugins/uci/Makefile
 	src/libcharon/plugins/ha/Makefile
 	src/libcharon/plugins/kernel_libipsec/Makefile
+	src/libcharon/plugins/kernel_wfp/Makefile
+	src/libcharon/plugins/kernel_iph/Makefile
 	src/libcharon/plugins/whitelist/Makefile
 	src/libcharon/plugins/lookip/Makefile
 	src/libcharon/plugins/error_notify/Makefile
@@ -1575,6 +1691,7 @@ AC_CONFIG_FILES([
 	src/libcharon/plugins/android_log/Makefile
 	src/libcharon/plugins/maemo/Makefile
 	src/libcharon/plugins/stroke/Makefile
+	src/libcharon/plugins/vici/Makefile
 	src/libcharon/plugins/updown/Makefile
 	src/libcharon/plugins/dhcp/Makefile
 	src/libcharon/plugins/unit_tester/Makefile
@@ -1582,10 +1699,12 @@ AC_CONFIG_FILES([
 	src/stroke/Makefile
 	src/ipsec/Makefile
 	src/starter/Makefile
+	src/starter/tests/Makefile
 	src/_updown/Makefile
 	src/_updown_espmark/Makefile
 	src/_copyright/Makefile
 	src/scepclient/Makefile
+	src/aikgen/Makefile
 	src/pki/Makefile
 	src/pki/man/Makefile
 	src/pool/Makefile
@@ -1597,6 +1716,7 @@ AC_CONFIG_FILES([
 	src/checksum/Makefile
 	src/conftest/Makefile
 	src/pt-tls-client/Makefile
+	src/swanctl/Makefile
 	scripts/Makefile
 	testing/Makefile
 ])
@@ -1623,6 +1743,9 @@ AC_CONFIG_FILES([
 	src/pki/man/pki---signcrl.1
 	src/pki/man/pki---acert.1
 	src/pki/man/pki---verify.1
+	src/swanctl/swanctl.8
+	src/swanctl/swanctl.conf.5.head
+	src/swanctl/swanctl.conf.5.tail
 ])
 
 AC_OUTPUT
diff --git a/init/Makefile.in b/init/Makefile.in
index 9937f3b..b48d335 100644
--- a/init/Makefile.in
+++ b/init/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -240,6 +240,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -258,6 +259,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -285,6 +287,7 @@ 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@
@@ -376,6 +379,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/init/systemd/Makefile.in b/init/systemd/Makefile.in
index 18d789d..27a767c 100644
--- a/init/systemd/Makefile.in
+++ b/init/systemd/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -209,6 +209,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -227,6 +228,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -254,6 +256,7 @@ 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@
@@ -345,6 +348,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/man/Makefile.in b/man/Makefile.in
index 72312c4..bd3141d 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -211,6 +211,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -229,6 +230,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -256,6 +258,7 @@ 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@
@@ -347,6 +350,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in
index a0be755..0f8564a 100644
--- a/man/ipsec.conf.5.in
+++ b/man/ipsec.conf.5.in
@@ -1049,6 +1049,15 @@ below.
 synonym for
 .BR margintime .
 .TP
+.BR replay_window " = " \-1 " | <number>"
+The IPsec replay window size for this connection. With the default of \-1
+the value configured with
+.I charon.replay_window
+in
+.BR strongswan.conf (5)
+is used. Larger values than 32 are supported using the Netlink backend only,
+a value of 0 disables IPsec replay protection.
+.TP
 .BR reqid " = <number>"
 sets the reqid for a given connection to a pre-configured fixed value.
 .TP
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index ed5147a..abc6d75 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 
 noinst_PROGRAMS = bin2array bin2sql id2sql key2keyid keyid2sql oid2der \
 	thread_analysis dh_speed pubkey_speed crypt_burn hash_burn fetch \
-	dnssec malloc_speed aes-test
+	dnssec malloc_speed aes-test settings-test
 
 if USE_TLS
   noinst_PROGRAMS += tls_test
@@ -40,6 +40,7 @@ malloc_speed_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(RTLIB)
 fetch_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 dnssec_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 aes_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 
 key2keyid.o :	$(top_builddir)/config.status
 
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index f55ce75..7343465 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -83,7 +83,7 @@ noinst_PROGRAMS = bin2array$(EXEEXT) bin2sql$(EXEEXT) id2sql$(EXEEXT) \
 	thread_analysis$(EXEEXT) dh_speed$(EXEEXT) \
 	pubkey_speed$(EXEEXT) crypt_burn$(EXEEXT) hash_burn$(EXEEXT) \
 	fetch$(EXEEXT) dnssec$(EXEEXT) malloc_speed$(EXEEXT) \
-	aes-test$(EXEEXT) $(am__EXEEXT_1)
+	aes-test$(EXEEXT) settings-test$(EXEEXT) $(am__EXEEXT_1)
 @USE_TLS_TRUE at am__append_1 = tls_test
 subdir = scripts
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
@@ -169,6 +169,10 @@ pubkey_speed_OBJECTS = $(am_pubkey_speed_OBJECTS)
 pubkey_speed_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(am__DEPENDENCIES_1)
+settings_test_SOURCES = settings-test.c
+settings_test_OBJECTS = settings-test.$(OBJEXT)
+settings_test_DEPENDENCIES =  \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la
 am_thread_analysis_OBJECTS = thread_analysis.$(OBJEXT)
 thread_analysis_OBJECTS = $(am_thread_analysis_OBJECTS)
 thread_analysis_LDADD = $(LDADD)
@@ -216,15 +220,15 @@ SOURCES = aes-test.c $(bin2array_SOURCES) $(bin2sql_SOURCES) \
 	$(fetch_SOURCES) $(hash_burn_SOURCES) $(id2sql_SOURCES) \
 	$(key2keyid_SOURCES) $(keyid2sql_SOURCES) \
 	$(malloc_speed_SOURCES) $(oid2der_SOURCES) \
-	$(pubkey_speed_SOURCES) $(thread_analysis_SOURCES) \
-	$(tls_test_SOURCES)
+	$(pubkey_speed_SOURCES) settings-test.c \
+	$(thread_analysis_SOURCES) $(tls_test_SOURCES)
 DIST_SOURCES = aes-test.c $(bin2array_SOURCES) $(bin2sql_SOURCES) \
 	$(crypt_burn_SOURCES) $(dh_speed_SOURCES) $(dnssec_SOURCES) \
 	$(fetch_SOURCES) $(hash_burn_SOURCES) $(id2sql_SOURCES) \
 	$(key2keyid_SOURCES) $(keyid2sql_SOURCES) \
 	$(malloc_speed_SOURCES) $(oid2der_SOURCES) \
-	$(pubkey_speed_SOURCES) $(thread_analysis_SOURCES) \
-	$(am__tls_test_SOURCES_DIST)
+	$(pubkey_speed_SOURCES) settings-test.c \
+	$(thread_analysis_SOURCES) $(am__tls_test_SOURCES_DIST)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -312,6 +316,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -330,6 +335,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -357,6 +363,7 @@ 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@
@@ -448,6 +455,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -493,6 +501,7 @@ malloc_speed_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(RTLIB)
 fetch_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 dnssec_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 aes_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 all: all-am
 
 .SUFFIXES:
@@ -593,6 +602,10 @@ pubkey_speed$(EXEEXT): $(pubkey_speed_OBJECTS) $(pubkey_speed_DEPENDENCIES) $(EX
 	@rm -f pubkey_speed$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(pubkey_speed_OBJECTS) $(pubkey_speed_LDADD) $(LIBS)
 
+settings-test$(EXEEXT): $(settings_test_OBJECTS) $(settings_test_DEPENDENCIES) $(EXTRA_settings_test_DEPENDENCIES) 
+	@rm -f settings-test$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(settings_test_OBJECTS) $(settings_test_LDADD) $(LIBS)
+
 thread_analysis$(EXEEXT): $(thread_analysis_OBJECTS) $(thread_analysis_DEPENDENCIES) $(EXTRA_thread_analysis_DEPENDENCIES) 
 	@rm -f thread_analysis$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(thread_analysis_OBJECTS) $(thread_analysis_LDADD) $(LIBS)
@@ -621,6 +634,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/malloc_speed.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/oid2der.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/pubkey_speed.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/settings-test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/thread_analysis.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tls_test.Po at am__quote@
 
diff --git a/scripts/hash_burn.c b/scripts/hash_burn.c
index 97eab0d..0aa9bf1 100644
--- a/scripts/hash_burn.c
+++ b/scripts/hash_burn.c
@@ -43,8 +43,7 @@ int main(int argc, char *argv[])
 		limit = atoi(argv[2]);
 	}
 
-	alg = enum_from_name(hash_algorithm_short_names, argv[1]);
-	if (alg == -1)
+	if (!enum_from_name(hash_algorithm_short_names, argv[1], &alg))
 	{
 		fprintf(stderr, "unknown hash algorthm: %s\n", argv[1]);
 		return 1;
diff --git a/scripts/settings-test.c b/scripts/settings-test.c
new file mode 100644
index 0000000..452798a
--- /dev/null
+++ b/scripts/settings-test.c
@@ -0,0 +1,126 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include <library.h>
+#include <settings/settings_types.h>
+
+/**
+ * Defined in libstrongswan but not part of the public API
+ */
+bool settings_parser_parse_file(void *this, char *name);
+
+/**
+ * Recursively print the section and all subsections/settings
+ */
+static void print_section(section_t *section, int level)
+{
+	section_t *sub;
+	kv_t *kv;
+	int i;
+	char indent[256];
+
+	for (i = 0; i < level * 2 && i < sizeof(indent) - 2; i += 2)
+	{
+		indent[i  ] = ' ';
+		indent[i+1] = ' ';
+	}
+	indent[i] = '\0';
+
+	for (i = 0; i < array_count(section->kv_order); i++)
+	{
+		array_get(section->kv_order, i, &kv);
+		printf("%s%s = %s\n", indent, kv->key, kv->value);
+	}
+	for (i = 0; i < array_count(section->sections_order); i++)
+	{
+		array_get(section->sections_order, i, &sub);
+		printf("%s%s {\n", indent, sub->name);
+		print_section(sub, level + 1);
+		printf("%s}\n", indent);
+	}
+}
+
+static void usage(FILE *out, char *name)
+{
+	fprintf(out, "Test strongswan.conf parser\n\n");
+	fprintf(out, "%s [OPTIONS]\n\n", name);
+	fprintf(out, "Options:\n");
+	fprintf(out, "  -h, --help          print this help.\n");
+	fprintf(out, "  -d, --debug         enables debugging of the parser.\n");
+	fprintf(out, "  -f, --file=FILE     config file to load (default STDIN).\n");
+	fprintf(out, "\n");
+}
+
+int main(int argc, char *argv[])
+{
+	char *file = NULL;
+
+	/* don't load strongswan.conf */
+	library_init("", "settings-test");
+	atexit(library_deinit);
+
+	dbg_default_set_level(3);
+
+	while (true)
+	{
+		struct option long_opts[] = {
+			{"help",		no_argument,		NULL,	'h' },
+			{"debug",		no_argument,		NULL,	'd' },
+			{"file",		required_argument,	NULL,	'f' },
+			{0,0,0,0 },
+		};
+		switch (getopt_long(argc, argv, "hdf:", long_opts, NULL))
+		{
+			case EOF:
+				break;
+			case 'h':
+				usage(stdout, argv[0]);
+				return 0;
+			case 'd':
+				setenv("DEBUG_SETTINGS_PARSER", "1", TRUE);
+				continue;
+			case 'f':
+				file = optarg;
+				continue;
+			default:
+				usage(stderr, argv[0]);
+				return 1;
+		}
+		break;
+	}
+
+	if (file)
+	{
+		section_t *root = settings_section_create(strdup("root"));
+
+		settings_parser_parse_file(root, file);
+
+		print_section(root, 0);
+
+		settings_section_destroy(root, NULL);
+	}
+	else
+	{
+		usage(stderr, argv[0]);
+	}
+	return 0;
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 93da489..95c68d0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -72,8 +72,16 @@ if USE_UPDOWN
   SUBDIRS += _updown _updown_espmark
 endif
 
-if USE_TOOLS
-  SUBDIRS += scepclient pki
+if USE_SCEPCLIENT
+  SUBDIRS += scepclient
+endif
+
+if USE_PKI
+  SUBDIRS += pki
+endif
+
+if USE_SWANCTL
+  SUBDIRS += swanctl
 endif
 
 if USE_CONFTEST
@@ -112,6 +120,10 @@ if USE_CMD
   SUBDIRS += charon-cmd
 endif
 
+if USE_SVC
+  SUBDIRS += charon-svc
+endif
+
 if USE_LIBPTTLS
   SUBDIRS += pt-tls-client
 endif
@@ -119,3 +131,7 @@ endif
 if USE_INTEGRITY_TEST
   SUBDIRS += checksum
 endif
+
+if USE_AIKGEN
+  SUBDIRS += aikgen
+endif
diff --git a/src/Makefile.in b/src/Makefile.in
index d1950d1..141ca3e 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -95,18 +95,22 @@ host_triplet = @host@
 @USE_NM_TRUE at am__append_16 = charon-nm
 @USE_STROKE_TRUE at am__append_17 = stroke
 @USE_UPDOWN_TRUE at am__append_18 = _updown _updown_espmark
- at USE_TOOLS_TRUE@am__append_19 = scepclient pki
- at USE_CONFTEST_TRUE@am__append_20 = conftest
- at USE_DUMM_TRUE@am__append_21 = dumm
- at USE_FAST_TRUE@am__append_22 = libfast
- at USE_MANAGER_TRUE@am__append_23 = manager
- at USE_MEDSRV_TRUE@am__append_24 = medsrv
- at USE_ATTR_SQL_TRUE@am__append_25 = pool
- at USE_ATTR_SQL_FALSE@@USE_SQL_TRUE at am__append_26 = pool
- at USE_TKM_TRUE@am__append_27 = charon-tkm
- at USE_CMD_TRUE@am__append_28 = charon-cmd
- at USE_LIBPTTLS_TRUE@am__append_29 = pt-tls-client
- at USE_INTEGRITY_TEST_TRUE@am__append_30 = checksum
+ 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
 subdir = src
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -183,9 +187,9 @@ CTAGS = ctags
 DIST_SUBDIRS = . include libstrongswan libhydra libipsec libsimaka \
 	libtls libradius libtncif libtnccs libpttls libimcv libpts \
 	libcharon starter ipsec _copyright charon charon-nm stroke \
-	_updown _updown_espmark scepclient pki conftest dumm libfast \
-	manager medsrv pool charon-tkm charon-cmd pt-tls-client \
-	checksum
+	_updown _updown_espmark 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`; \
@@ -274,6 +278,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -292,6 +297,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -319,6 +325,7 @@ 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@
@@ -410,6 +417,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -429,7 +437,9 @@ SUBDIRS = . include $(am__append_1) $(am__append_2) $(am__append_3) \
 	$(am__append_19) $(am__append_20) $(am__append_21) \
 	$(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_28) $(am__append_29) $(am__append_30) \
+	$(am__append_31) $(am__append_32) $(am__append_33) \
+	$(am__append_34)
 all: all-recursive
 
 .SUFFIXES:
diff --git a/src/_copyright/Makefile.in b/src/_copyright/Makefile.in
index 4377ca0..8591e6a 100644
--- a/src/_copyright/Makefile.in
+++ b/src/_copyright/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -232,6 +232,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -250,6 +251,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -277,6 +279,7 @@ 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@
@@ -368,6 +371,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/_updown/Makefile.in b/src/_updown/Makefile.in
index b015e3d..ec23208 100644
--- a/src/_updown/Makefile.in
+++ b/src/_updown/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -213,6 +213,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -231,6 +232,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -258,6 +260,7 @@ 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@
@@ -349,6 +352,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/_updown_espmark/Makefile.in b/src/_updown_espmark/Makefile.in
index ee814a4..49cdc90 100644
--- a/src/_updown_espmark/Makefile.in
+++ b/src/_updown_espmark/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -213,6 +213,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -231,6 +232,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -258,6 +260,7 @@ 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@
@@ -349,6 +352,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/aikgen/Makefile.am b/src/aikgen/Makefile.am
new file mode 100644
index 0000000..dc59d20
--- /dev/null
+++ b/src/aikgen/Makefile.am
@@ -0,0 +1,15 @@
+bin_PROGRAMS = aikgen
+
+aikgen_SOURCES = aikgen.c
+
+aikgen_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+aikgen.o :	$(top_builddir)/config.status
+
+if USE_TROUSERS
+  aikgen_LDADD += -ltspi
+endif
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
+	-DPLUGINS=\""${aikgen_plugins}\""
diff --git a/src/aikgen/Makefile.in b/src/aikgen/Makefile.in
new file mode 100644
index 0000000..77d825f
--- /dev/null
+++ b/src/aikgen/Makefile.in
@@ -0,0 +1,731 @@
+# 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@
+bin_PROGRAMS = aikgen$(EXEEXT)
+ at USE_TROUSERS_TRUE@am__append_1 = -ltspi
+subdir = src/aikgen
+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__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_aikgen_OBJECTS = aikgen.$(OBJEXT)
+aikgen_OBJECTS = $(am_aikgen_OBJECTS)
+am__DEPENDENCIES_1 =
+aikgen_DEPENDENCIES =  \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(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
+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 = $(aikgen_SOURCES)
+DIST_SOURCES = $(aikgen_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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@
+aikgen_SOURCES = aikgen.c
+aikgen_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(am__append_1)
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
+	-DPLUGINS=\""${aikgen_plugins}\""
+
+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/aikgen/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/aikgen/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-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+	@list='$(bin_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
+
+aikgen$(EXEEXT): $(aikgen_OBJECTS) $(aikgen_DEPENDENCIES) $(EXTRA_aikgen_DEPENDENCIES) 
+	@rm -f aikgen$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(aikgen_OBJECTS) $(aikgen_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aikgen.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 $@ $<
+
+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 $(PROGRAMS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)"; 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-binPROGRAMS 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-binPROGRAMS
+
+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-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+	clean-binPROGRAMS 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-binPROGRAMS \
+	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 uninstall-binPROGRAMS
+
+aikgen.o :	$(top_builddir)/config.status
+
+# 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/aikgen/aikgen.c b/src/aikgen/aikgen.c
new file mode 100644
index 0000000..192636a
--- /dev/null
+++ b/src/aikgen/aikgen.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2014 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * Copyright (c) 2008 Hal Finney
+ *
+ * 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 <library.h>
+#include <utils/debug.h>
+#include <utils/optionsfrom.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/keys/public_key.h>
+#include <asn1/oid.h>
+#include <asn1/asn1.h>
+
+#include <trousers/tss.h>
+#include <trousers/trousers.h>
+
+#include <syslog.h>
+#include <getopt.h>
+#include <errno.h>
+
+/* default directory where AIK keys are stored */
+#define AIK_DIR							IPSEC_CONFDIR "/pts/"
+
+/* default name of AIK private key blob */
+#define DEFAULT_FILENAME_AIKBLOB		AIK_DIR "aikBlob.bin"
+
+/* default name of AIK private key blob */
+#define DEFAULT_FILENAME_AIKPUBKEY		AIK_DIR "aikPub.der"
+
+/* size in bytes of a TSS AIK public key blob */
+#define AIK_PUBKEY_BLOB_SIZE			284
+
+/* logging */
+static bool log_to_stderr = TRUE;
+static bool log_to_syslog = TRUE;
+static level_t default_loglevel = 1;
+
+/* options read by optionsfrom */
+options_t *options;
+
+/* global variables */
+certificate_t *cacert;
+public_key_t *ca_pubkey;
+chunk_t ca_modulus;
+chunk_t aik_pubkey;
+chunk_t aik_keyid;
+
+/* TPM context */
+TSS_HCONTEXT  hContext;
+
+/**
+ * logging function for aikgen
+ */
+static void aikgen_dbg(debug_t group, level_t level, char *fmt, ...)
+{
+	char buffer[8192];
+	char *current = buffer, *next;
+	va_list args;
+
+	if (level <= default_loglevel)
+	{
+		if (log_to_stderr)
+		{
+			va_start(args, fmt);
+			vfprintf(stderr, fmt, args);
+			va_end(args);
+			fprintf(stderr, "\n");
+		}
+		if (log_to_syslog)
+		{
+			/* write in memory buffer first */
+			va_start(args, fmt);
+			vsnprintf(buffer, sizeof(buffer), fmt, args);
+			va_end(args);
+
+			/* do a syslog with every line */
+			while (current)
+			{
+				next = strchr(current, '\n');
+				if (next)
+				{
+					*(next++) = '\0';
+				}
+				syslog(LOG_INFO, "%s\n", current);
+				current = next;
+			}
+		}
+	}
+}
+
+/**
+ * Initialize logging to stderr/syslog
+ */
+static void init_log(const char *program)
+{
+	dbg = aikgen_dbg;
+
+	if (log_to_stderr)
+	{
+		setbuf(stderr, NULL);
+	}
+	if (log_to_syslog)
+	{
+		openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
+	}
+}
+
+/**
+ * @brief exit aikgen
+ *
+ * @param status 0 = OK, 1 = general discomfort
+ */
+static void exit_aikgen(err_t message, ...)
+{
+	int status = 0;
+
+	DESTROY_IF(cacert);
+	DESTROY_IF(ca_pubkey);
+	free(ca_modulus.ptr);
+	free(aik_pubkey.ptr);
+	free(aik_keyid.ptr);
+	options->destroy(options);
+
+	/* clean up TPM context */
+	if (hContext)
+	{
+		Tspi_Context_FreeMemory(hContext, NULL);
+		Tspi_Context_Close(hContext);
+	}
+
+	/* print any error message to stderr */
+	if (message != NULL && *message != '\0')
+	{
+		va_list args;
+		char m[8192];
+
+		va_start(args, message);
+		vsnprintf(m, sizeof(m), message, args);
+		va_end(args);
+
+		fprintf(stderr, "error: %s\n", m);
+		status = -1;
+	}
+	library_deinit();
+	exit(status);
+}
+
+/**
+ * @brief prints the usage of the program to the stderr output
+ *
+ * If message is set, program is exited with 1 (error)
+ * @param message message in case of an error
+ */
+static void usage(const char *message)
+{
+	fprintf(stderr,
+		"Usage: aikgen  --cacert|capubkey <filename>"
+		" [--aikblob <filename>] [--aikpubkey <filename>] \n"
+		"              [--idreq <filename>] [--force]"
+		" [--quiet] [--debug <level>]\n"
+		"       aikgen --help\n"
+		"\n"
+		"Options:\n"
+		" --cacert (-c)     certificate of [privacy] CA\n"
+		" --capubkey (-k)   public key of [privacy] CA\n"
+		" --aikblob (-b)    encrypted blob with AIK private key\n"
+		" --aikpubkey (-p)  AIK public key\n"
+		" --idreq (-i)      encrypted identity request\n"
+		" --force (-f)      force to overwrite existing files\n"
+		" --help (-h)       show usage and exit\n"
+		"\n"
+		"Debugging output:\n"
+		" --debug (-l)      changes the log level (-1..4, default: 1)\n"
+		" --quiet (-q)      do not write log output to stderr\n"
+		);
+	exit_aikgen(message);
+}
+
+/**
+ * @brief main of aikgen which generates an Attestation Identity Key (AIK)
+ *
+ * @param argc number of arguments
+ * @param argv pointer to the argument values
+ */
+int main(int argc, char *argv[])
+{
+	/* external values */
+	extern char * optarg;
+	extern int optind;
+
+	char *cacert_filename    = NULL;
+	char *capubkey_filename  = NULL;
+	char *aikblob_filename   = DEFAULT_FILENAME_AIKBLOB;
+	char *aikpubkey_filename = DEFAULT_FILENAME_AIKPUBKEY;
+	char *idreq_filename     = NULL;
+	bool force = FALSE;
+	chunk_t identity_req;
+	chunk_t aik_blob;
+	chunk_t aik_pubkey_blob;
+	chunk_t aik_modulus;
+	chunk_t aik_exponent;
+
+	/* TPM variables */
+	TSS_RESULT   result;
+	TSS_HTPM     hTPM;
+	TSS_HKEY     hSRK;
+	TSS_HKEY     hPCAKey;
+	TSS_HPOLICY  hSrkPolicy;
+	TSS_HPOLICY  hTPMPolicy;
+	TSS_HKEY     hIdentKey;
+	TSS_UUID     SRK_UUID = TSS_UUID_SRK;
+	BYTE         secret[] = TSS_WELL_KNOWN_SECRET;
+	BYTE        *IdentityReq;
+	UINT32       IdentityReqLen;
+	BYTE        *blob;
+	UINT32       blobLen;
+
+	atexit(library_deinit);
+	if (!library_init(NULL, "aikgen"))
+	{
+		exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+	}
+	if (lib->integrity &&
+		!lib->integrity->check_file(lib->integrity, "aikgen", argv[0]))
+	{
+		fprintf(stderr, "integrity check of aikgen failed\n");
+		exit(SS_RC_DAEMON_INTEGRITY);
+	}
+
+	/* initialize global variables */
+	options = options_create();
+
+	for (;;)
+	{
+		static const struct option long_opts[] = {
+			/* name, has_arg, flag, val */
+			{ "help", no_argument, NULL, 'h' },
+			{ "optionsfrom", required_argument, NULL, '+' },
+			{ "cacert", required_argument, NULL, 'c' },
+			{ "capubkey", required_argument, NULL, 'k' },
+			{ "aikblob", required_argument, NULL, 'b' },
+			{ "aikpubkey", required_argument, NULL, 'p' },
+			{ "idreq", required_argument, NULL, 'i' },
+			{ "force", no_argument, NULL, 'f' },
+			{ "quiet", no_argument, NULL, 'q' },
+			{ "debug", required_argument, NULL, 'l' },
+			{ 0,0,0,0 }
+		};
+
+		/* parse next option */
+		int c = getopt_long(argc, argv, "ho:c:b:p:fqd:", long_opts, NULL);
+
+		switch (c)
+		{
+			case EOF:       /* end of flags */
+				break;
+
+			case 'h':       /* --help */
+				usage(NULL);
+
+			case '+':       /* --optionsfrom <filename> */
+				if (!options->from(options, optarg, &argc, &argv, optind))
+				{
+					exit_aikgen("optionsfrom failed");
+				}
+				continue;
+
+			case 'c':       /* --cacert <filename> */
+				cacert_filename = optarg;
+				continue;
+
+			case 'k':       /* --capubkey <filename> */
+				capubkey_filename = optarg;
+				continue;
+
+			case 'b':       /* --aikblob <filename> */
+				aikblob_filename = optarg;
+				continue;
+
+			case 'p':       /* --aikpubkey <filename> */
+				aikpubkey_filename = optarg;
+				continue;
+
+			case 'i':       /* --idreq <filename> */
+				idreq_filename = optarg;
+				continue;
+
+			case 'f':       /* --force */
+				force = TRUE;
+				continue;
+
+			case 'q':       /* --quiet */
+				log_to_stderr = FALSE;
+				continue;
+
+			case 'l':		/* --debug <level> */
+				default_loglevel = atoi(optarg);
+				continue;
+
+			default:
+				usage("unknown option");
+		}
+		/* break from loop */
+		break;
+	}
+
+	init_log("aikgen");
+
+	if (!lib->plugins->load(lib->plugins,
+			lib->settings->get_str(lib->settings, "aikgen.load", PLUGINS)))
+	{
+		exit_aikgen("plugin loading failed");
+	}
+
+	/* read certificate of [privacy] CA if it exists */
+	if (cacert_filename)
+	{
+		cacert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+								BUILD_FROM_FILE, cacert_filename, BUILD_END);
+		if (!cacert)
+		{
+			exit_aikgen("could not read ca certificate file '%s'",
+						 cacert_filename);
+		}
+	}
+
+	/* optionally read public key of [privacy CA] if it exists */
+	if (!cacert)
+	{
+		if (!capubkey_filename)
+		{
+			usage("either --cacert or --capubkey option is required");
+		}
+		cacert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+								CERT_TRUSTED_PUBKEY, BUILD_FROM_FILE,
+								capubkey_filename, BUILD_END);
+		if (!cacert)
+		{
+			exit_aikgen("could not read ca public key file '%s'",
+						 capubkey_filename);
+		}
+	}
+
+	/* extract public key from CA certificate or trusted CA public key */
+	ca_pubkey = cacert->get_public_key(cacert);
+	if (!ca_pubkey)
+	{
+		exit_aikgen("could not extract ca public key");
+	}
+	if (ca_pubkey->get_type(ca_pubkey) != KEY_RSA ||
+		ca_pubkey->get_keysize(ca_pubkey) != 2048)
+	{
+		exit_aikgen("ca public key must be RSA 2048 but is %N %d",
+					 key_type_names, ca_pubkey->get_type(ca_pubkey),
+					 ca_pubkey->get_keysize(ca_pubkey));
+	}
+	if (!ca_pubkey->get_encoding(ca_pubkey, PUBKEY_RSA_MODULUS, &ca_modulus))
+	{
+		exit_aikgen("could not extract RSA modulus from ca public key");
+	}
+
+	/* initialize TSS context and connect to it */
+	result = Tspi_Context_Create(&hContext);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Context_Create", result);
+	}
+	result = Tspi_Context_Connect(hContext, NULL);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Context_Connect", result);
+	}
+
+	/* get SRK plus SRK policy and set SRK secret */
+	result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM,
+										SRK_UUID, &hSRK);
+ 	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Context_LoadKeyByUUID for SRK", result);
+	}
+	result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_GetPolicyObject for SRK", result);
+	}
+	result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Policy_SetSecret for SRK", result);
+	}
+
+	/* get TPM plus TPM policy and set TPM secret */
+	result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Context_GetTpmObject", result);
+	}
+	result = Tspi_GetPolicyObject(hTPM, TSS_POLICY_USAGE, &hTPMPolicy);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_GetPolicyObject for TPM", result);
+	}
+	result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Policy_SetSecret for TPM", result);
+	}
+
+	/* create context for a 2048 bit AIK */
+	result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
+					TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048 |
+					TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE, &hIdentKey);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Context_CreateObject for key", result);
+	}
+
+	/* create context for the Privacy CA public key and assign modulus */
+	result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
+					TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048, &hPCAKey);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Context_CreateObject for PCA", result);
+	}
+	result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO,
+					TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, ca_modulus.len,
+					ca_modulus.ptr);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_SetAttribData for PCA modulus", result);
+	}
+	result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO,
+					TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_SetAttribUint32 for PCA "
+					"encryption scheme", result);
+	}
+
+	/* generate AIK */
+	DBG1(DBG_LIB, "Generating identity key...");
+	result = Tspi_TPM_CollateIdentityRequest(hTPM, hSRK, hPCAKey, 0, NULL,
+					hIdentKey, TSS_ALG_AES,	&IdentityReqLen, &IdentityReq);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_TPM_CollateIdentityRequest", result);
+	}
+	identity_req = chunk_create(IdentityReq, IdentityReqLen);
+	DBG3(DBG_LIB, "Identity Request: %B", &identity_req);
+
+	/* optionally output identity request encrypted with ca public key */
+	if (idreq_filename)
+	{
+		if (!chunk_write(identity_req, idreq_filename, 0022, force))
+		{
+			exit_aikgen("could not write AIK identity request file '%s': %s",
+						 idreq_filename, strerror(errno));
+		}
+		DBG1(DBG_LIB, "AIK identity request written to '%s' (%u bytes)",
+					   idreq_filename, identity_req.len);
+	}
+
+	/* load identity key */
+	result = Tspi_Key_LoadKey (hIdentKey, hSRK);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_Key_LoadKey for AIK\n", result);
+	}
+
+	/* output AIK private key in TSS blob format */
+	result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
+					TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_GetAttribData for private key blob",
+					 result);
+	}
+	aik_blob = chunk_create(blob, blobLen);
+	DBG3(DBG_LIB, "AIK private key blob: %B", &aik_blob);
+
+	if (!chunk_write(aik_blob, aikblob_filename, 0022, force))
+	{
+		exit_aikgen("could not write AIK blob file '%s': %s",
+					 aikblob_filename, strerror(errno));
+	}
+	DBG1(DBG_LIB, "AIK private key blob written to '%s' (%u bytes)",
+				   aikblob_filename, aik_blob.len);
+
+	/* output AIK Public Key in TSS blob format */
+	result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
+					TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blobLen, &blob);
+	if (result != TSS_SUCCESS)
+	{
+		exit_aikgen("tss 0x%x on Tspi_GetAttribData for public key blob",
+					 result);
+	}
+	aik_pubkey_blob = chunk_create(blob, blobLen);
+	DBG3(DBG_LIB, "AIK public key blob: %B", &aik_pubkey_blob);
+
+	/* create a trusted AIK public key */
+	if (aik_pubkey_blob.len != AIK_PUBKEY_BLOB_SIZE)
+	{
+		exit_aikgen("AIK public key is not in TSS blob format");
+	}
+	aik_modulus = chunk_skip(aik_pubkey_blob, AIK_PUBKEY_BLOB_SIZE - 256);
+	aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
+
+	/* output subjectPublicKeyInfo encoding of AIK public key */
+	if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL,
+					&aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
+					CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
+	{
+		exit_aikgen("subjectPublicKeyInfo encoding of AIK key failed");
+	}
+	if (!chunk_write(aik_pubkey, aikpubkey_filename, 0022, force))
+	{
+		exit_aikgen("could not write AIK public key file '%s': %s",
+					 aikpubkey_filename, strerror(errno));
+	}
+	DBG1(DBG_LIB, "AIK public key written to '%s' (%u bytes)",
+				   aikpubkey_filename, aik_pubkey.len);
+
+	/* display AIK keyid derived from subjectPublicKeyInfo encoding */
+	if (!lib->encoding->encode(lib->encoding, KEYID_PUBKEY_INFO_SHA1, NULL,
+					&aik_keyid, CRED_PART_RSA_MODULUS, aik_modulus,
+					CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
+	{
+		exit_aikgen("computation of AIK keyid failed");
+	}
+	DBG1(DBG_LIB, "AIK keyid: %#B", &aik_keyid);
+
+	exit_aikgen(NULL);
+	return -1; /* should never be reached */
+}
diff --git a/src/charon-cmd/Makefile.in b/src/charon-cmd/Makefile.in
index 0e5c00a..c74c5b6 100644
--- a/src/charon-cmd/Makefile.in
+++ b/src/charon-cmd/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ 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@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/charon-cmd/charon-cmd.c b/src/charon-cmd/charon-cmd.c
index a70d314..b41cf46 100644
--- a/src/charon-cmd/charon-cmd.c
+++ b/src/charon-cmd/charon-cmd.c
@@ -126,12 +126,15 @@ static int run()
 			{
 				DBG1(DBG_DMN, "signal of type SIGHUP received. Reloading "
 					 "configuration");
-				if (lib->settings->load_files(lib->settings, NULL, FALSE))
+#ifdef STRONGSWAN_CONF
+				if (lib->settings->load_files(lib->settings, STRONGSWAN_CONF,
+											  FALSE))
 				{
 					charon->load_loggers(charon, levels, TRUE);
 					lib->plugins->reload(lib->plugins, NULL);
 				}
 				else
+#endif
 				{
 					DBG1(DBG_DMN, "reloading config failed, keeping old");
 				}
diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
index ac085e1..2c0b7b9 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -187,6 +187,7 @@ static peer_cfg_t* create_peer_cfg(private_cmd_connection_t *this)
 	else
 	{
 		ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+		ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 	}
 	peer_cfg = peer_cfg_create("cmd", ike_cfg,
 					CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
@@ -357,6 +358,8 @@ static child_cfg_t* create_child_cfg(private_cmd_connection_t *this,
 	else
 	{
 		child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+		child_cfg->add_proposal(child_cfg,
+								proposal_create_default_aead(PROTO_ESP));
 	}
 	while (this->local_ts->remove_first(this->local_ts, (void**)&ts) == SUCCESS)
 	{
@@ -460,10 +463,9 @@ static void add_ts(private_cmd_connection_t *this,
  */
 static void set_profile(private_cmd_connection_t *this, char *name)
 {
-	int profile;
+	profile_t profile;
 
-	profile = enum_from_name(profile_names, name);
-	if (profile == -1)
+	if (!enum_from_name(profile_names, name, &profile))
 	{
 		DBG1(DBG_CFG, "unknown connection profile: %s", name);
 		exit(1);
diff --git a/src/charon-cmd/cmd/cmd_creds.c b/src/charon-cmd/cmd/cmd_creds.c
index 7fee85d..45d008e 100644
--- a/src/charon-cmd/cmd/cmd_creds.c
+++ b/src/charon-cmd/cmd/cmd_creds.c
@@ -72,7 +72,7 @@ static shared_key_t* callback_shared(private_cmd_creds_t *this,
 								id_match_t *match_me, id_match_t *match_other)
 {
 	shared_key_t *shared;
-	char *label, *pwd;
+	char *label, *pwd = NULL;
 
 	if (type == this->prompted)
 	{
@@ -95,7 +95,9 @@ static shared_key_t* callback_shared(private_cmd_creds_t *this,
 		default:
 			return NULL;
 	}
+#ifdef HAVE_GETPASS
 	pwd = getpass(label);
+#endif
 	if (!pwd || strlen(pwd) == 0)
 	{
 		return NULL;
diff --git a/src/charon-nm/Makefile.in b/src/charon-nm/Makefile.in
index edc3d77..5fad214 100644
--- a/src/charon-nm/Makefile.in
+++ b/src/charon-nm/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -240,6 +240,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -258,6 +259,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -285,6 +287,7 @@ 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@
@@ -376,6 +379,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index 67366a0..fc7e899 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -532,6 +532,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
 							(char*)address, IKEV2_UDP_PORT,
 							 FRAGMENTATION_NO, 0);
 	ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+	ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 	peer_cfg = peer_cfg_create(priv->name, ike_cfg,
 					CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */
 					36000, 0, /* rekey 10h, reauth none */
@@ -565,6 +566,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
 								 ACTION_NONE, ACTION_NONE, ACTION_NONE, ipcomp,
 								 0, 0, NULL, NULL, 0);
 	child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+	child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
 	ts = traffic_selector_create_dynamic(0, 0, 65535);
 	child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
 	ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
diff --git a/src/charon-svc/Makefile.am b/src/charon-svc/Makefile.am
new file mode 100644
index 0000000..ecccf02
--- /dev/null
+++ b/src/charon-svc/Makefile.am
@@ -0,0 +1,16 @@
+bin_PROGRAMS = charon-svc
+
+charon_svc_SOURCES = charon-svc.c
+
+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
new file mode 100644
index 0000000..3948362
--- /dev/null
+++ b/src/charon-svc/Makefile.in
@@ -0,0 +1,735 @@
+# 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@
+bin_PROGRAMS = charon-svc$(EXEEXT)
+subdir = src/charon-svc
+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__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+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@)
+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 = $(charon_svc_SOURCES)
+DIST_SOURCES = $(charon_svc_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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@
+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
+
+.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/charon-svc/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/charon-svc/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-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+	@list='$(bin_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
+
+charon-svc$(EXEEXT): $(charon_svc_OBJECTS) $(charon_svc_DEPENDENCIES) $(EXTRA_charon_svc_DEPENDENCIES) 
+	@rm -f charon-svc$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(charon_svc_OBJECTS) $(charon_svc_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/charon-svc.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 $@ $<
+
+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 $(PROGRAMS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)"; 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-binPROGRAMS 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-binPROGRAMS
+
+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-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+	clean-binPROGRAMS 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-binPROGRAMS \
+	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 uninstall-binPROGRAMS
+
+
+charon-svc.o :	$(top_builddir)/config.status
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/charon-svc/charon-svc.c b/src/charon-svc/charon-svc.c
new file mode 100644
index 0000000..03cbdb8
--- /dev/null
+++ b/src/charon-svc/charon-svc.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+#include <hydra.h>
+#include <daemon.h>
+
+#include <utils/backtrace.h>
+#include <threading/thread.h>
+
+/**
+ * The name of our service, both internal and external
+ */
+#define SERVICE_NAME "charon-svc"
+
+/**
+ * Current service status
+ */
+static SERVICE_STATUS status;
+
+/**
+ * Handle for service status
+ */
+static SERVICE_STATUS_HANDLE handle;
+
+/**
+ * Wait event for main thread
+ */
+static HANDLE event;
+
+/**
+ * hook in library for debugging messages
+ */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * Forward declaration
+ */
+static DWORD WINAPI service_handler(DWORD dwControl, DWORD dwEventType,
+									LPVOID lpEventData, LPVOID lpContext);
+
+/**
+ * Logging hook for library logs, using stderr output
+ */
+static void dbg_stderr(debug_t group, level_t level, char *fmt, ...)
+{
+	va_list args;
+
+	if (level <= 1)
+	{
+		va_start(args, fmt);
+		fprintf(stderr, "00[%N] ", debug_names, group);
+		vfprintf(stderr, fmt, args);
+		fprintf(stderr, "\n");
+		va_end(args);
+	}
+}
+
+/**
+ * Log strongSwan/Windows version during startup
+ */
+static void print_version()
+{
+	OSVERSIONINFOEX osvie;
+
+	memset(&osvie, 0, sizeof(osvie));
+	osvie.dwOSVersionInfoSize = sizeof(osvie);
+
+	if (GetVersionEx((LPOSVERSIONINFO)&osvie))
+	{
+		DBG1(DBG_DMN, "Starting IKE service %s (strongSwan %s, "
+			 "Windows %s %d.%d.%d (SP %d.%d)", SERVICE_NAME, VERSION,
+			 osvie.wProductType == VER_NT_WORKSTATION ? "Client" : "Server",
+			 osvie.dwMajorVersion, osvie.dwMinorVersion, osvie.dwBuildNumber,
+			 osvie.wServicePackMajor, osvie.wServicePackMinor);
+	}
+}
+
+/**
+ * Update service state to SCM, increase check point if state didn't change
+ */
+static void update_status(DWORD state)
+{
+	if (state == status.dwCurrentState)
+	{
+		status.dwCheckPoint++;
+	}
+	else
+	{
+		status.dwCheckPoint = 0;
+	}
+	status.dwCurrentState = state;
+	if (handle)
+	{
+		SetServiceStatus(handle, &status);
+	}
+}
+
+/**
+ * Control handler for console
+ */
+static BOOL WINAPI console_handler(DWORD dwCtrlType)
+{
+	switch (dwCtrlType)
+	{
+		case CTRL_C_EVENT:
+		case CTRL_BREAK_EVENT:
+		case CTRL_CLOSE_EVENT:
+			DBG1(DBG_DMN, "application is stopping, cleaning up");
+			if (status.dwCurrentState == SERVICE_RUNNING)
+			{
+				charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL,
+								   dwCtrlType);
+			}
+			/* signal main thread to clean up */
+			SetEvent(event);
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
+
+/**
+ * Service handler function
+ */
+static DWORD WINAPI service_handler(DWORD dwControl, DWORD dwEventType,
+									LPVOID lpEventData, LPVOID lpContext)
+{
+	switch (dwControl)
+	{
+		case SERVICE_CONTROL_STOP:
+		case SERVICE_CONTROL_SHUTDOWN:
+			DBG1(DBG_DMN, "service is stopping, cleaning up");
+			if (status.dwCurrentState == SERVICE_RUNNING)
+			{
+				charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL,
+								   dwControl);
+			}
+			/* signal main thread to clean up */
+			SetEvent(event);
+			return NO_ERROR;
+		case SERVICE_CONTROL_INTERROGATE:
+			return NO_ERROR;
+		default:
+			return ERROR_CALL_NOT_IMPLEMENTED;
+	}
+}
+
+/**
+ * Wait for console program shutdown
+ */
+static int console_wait()
+{
+	update_status(SERVICE_RUNNING);
+
+	if (WaitForSingleObjectEx(event, INFINITE, TRUE) != WAIT_OBJECT_0)
+	{
+		return 2;
+	}
+	return 0;
+}
+
+/**
+ * Wait for service shutdown
+ */
+static int service_wait()
+{
+	/* service is initialized, we now accept control requests */
+	status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+	update_status(SERVICE_RUNNING);
+	status.dwControlsAccepted = 0;
+
+	if (WaitForSingleObjectEx(event, INFINITE, TRUE) != WAIT_OBJECT_0)
+	{
+		return 2;
+	}
+	return 0;
+}
+
+/**
+ * Initialize and run charon using a wait function
+ */
+static void init_and_run(DWORD dwArgc, LPTSTR *lpszArgv, int (*wait)())
+{
+	level_t levels[DBG_MAX];
+	int i;
+
+	for (i = 0; i < DBG_MAX; i++)
+	{
+		levels[i] = LEVEL_CTRL;
+	}
+
+	update_status(SERVICE_START_PENDING);
+	event = CreateEvent(NULL, FALSE, FALSE, NULL);
+	if (event)
+	{
+		update_status(SERVICE_START_PENDING);
+		if (library_init(NULL, SERVICE_NAME))
+		{
+			update_status(SERVICE_START_PENDING);
+			if (libhydra_init())
+			{
+				update_status(SERVICE_START_PENDING);
+				if (libcharon_init())
+				{
+					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);
+
+						charon->start(charon);
+
+						status.dwWin32ExitCode = wait();
+					}
+					update_status(SERVICE_STOP_PENDING);
+					libcharon_deinit();
+				}
+				update_status(SERVICE_STOP_PENDING);
+				libhydra_deinit();
+			}
+			update_status(SERVICE_STOP_PENDING);
+			library_deinit();
+		}
+		update_status(SERVICE_STOP_PENDING);
+		CloseHandle(event);
+	}
+	update_status(SERVICE_STOPPED);
+}
+
+/**
+ * Main routine when running from console
+ */
+static void console_main(DWORD dwArgc, LPTSTR *lpszArgv)
+{
+	status.dwWin32ExitCode = 1;
+
+	if (SetConsoleCtrlHandler(console_handler, TRUE))
+	{
+		init_and_run(dwArgc, lpszArgv, console_wait);
+		SetConsoleCtrlHandler(console_handler, FALSE);
+	}
+}
+
+/**
+ * Switch the working directory to the executable directory
+ */
+static bool switch_workingdir()
+{
+	CHAR path[MAX_PATH], *pos;
+	HMODULE module;
+
+	module = GetModuleHandle(NULL);
+	if (!module)
+	{
+		return FALSE;
+	}
+	if (!GetModuleFileName(module, path, sizeof(path)))
+	{
+		return FALSE;
+	}
+	pos = strrchr(path, '\\');
+	if (!pos)
+	{
+		return FALSE;
+	}
+	*pos = 0;
+	return SetCurrentDirectory(path);
+}
+
+/**
+ * Service main routine when running as service
+ */
+static void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
+{
+	memset(&status, 0, sizeof(status));
+	status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+	status.dwWin32ExitCode = 1;
+
+	handle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, service_handler, NULL);
+	if (handle)
+	{
+		if (switch_workingdir())
+		{
+			init_and_run(dwArgc, lpszArgv, service_wait);
+		}
+	}
+}
+
+/**
+ * Main function, starts the service
+ */
+int main(int argc, char *argv[])
+{
+	SERVICE_TABLE_ENTRY services[] = {
+		{
+			.lpServiceName = SERVICE_NAME,
+			.lpServiceProc = service_main,
+		},
+		{ NULL, NULL },
+	};
+	DWORD err;
+
+	dbg = dbg_stderr;
+
+	if (!StartServiceCtrlDispatcher(services))
+	{
+		err = GetLastError();
+		if (err == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
+		{
+			console_main(argc, argv);
+		}
+		else
+		{
+			return 2;
+		}
+	}
+	return status.dwWin32ExitCode;
+}
diff --git a/src/charon-tkm/Makefile.in b/src/charon-tkm/Makefile.in
index 8005d07..ca4cdbf 100644
--- a/src/charon-tkm/Makefile.in
+++ b/src/charon-tkm/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -179,6 +179,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -197,6 +198,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -224,6 +226,7 @@ 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@
@@ -315,6 +318,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
index 72c247d..dbeea93 100644
--- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
+++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
@@ -91,8 +91,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 	private_tkm_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, bool _initiator, bool encap, bool esn, bool inbound,
+	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,
 	traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
 	esa_info_t esa;
diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c
index 0505864..b2692a5 100644
--- a/src/charon-tkm/src/tkm/tkm_listener.c
+++ b/src/charon-tkm/src/tkm/tkm_listener.c
@@ -310,7 +310,7 @@ METHOD(listener_t, message, bool,
 	     " (ISA context %llu)", isa_id);
 
 	auth_payload = (auth_payload_t*)message->get_payload(message,
-														 AUTHENTICATION);
+														 PLV2_AUTH);
 	if (auth_payload)
 	{
 		chunk_t auth_data;
diff --git a/src/charon/Makefile.in b/src/charon/Makefile.in
index f808ce0..0e8a49e 100644
--- a/src/charon/Makefile.in
+++ b/src/charon/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -236,6 +236,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -254,6 +255,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -281,6 +283,7 @@ 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@
@@ -372,6 +375,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/charon/charon.c b/src/charon/charon.c
index 089ac45..8afac3f 100644
--- a/src/charon/charon.c
+++ b/src/charon/charon.c
@@ -26,6 +26,8 @@
 #include <sys/utsname.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <fcntl.h>
+#include <errno.h>
 
 #include <hydra.h>
 #include <daemon.h>
@@ -122,12 +124,15 @@ static void run()
 			{
 				DBG1(DBG_DMN, "signal of type SIGHUP received. Reloading "
 					 "configuration");
-				if (lib->settings->load_files(lib->settings, NULL, FALSE))
+#ifdef STRONGSWAN_CONF
+				if (lib->settings->load_files(lib->settings, STRONGSWAN_CONF,
+											  FALSE))
 				{
 					charon->load_loggers(charon, levels, !use_syslog);
 					lib->plugins->reload(lib->plugins, NULL);
 				}
 				else
+#endif
 				{
 					DBG1(DBG_DMN, "reloading config failed, keeping old");
 				}
@@ -229,6 +234,14 @@ static bool check_pidfile()
 	pidfile = fopen(PID_FILE, "w");
 	if (pidfile)
 	{
+		int fd;
+
+		fd = fileno(pidfile);
+		if (fd == -1 || fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
+		{
+			DBG1(DBG_LIB, "setting FD_CLOEXEC for '"PID_FILE"' failed: %s",
+				 strerror(errno));
+		}
 		ignore_result(fchown(fileno(pidfile),
 							 lib->caps->get_uid(lib->caps),
 							 lib->caps->get_gid(lib->caps)));
diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am
index 82bbadc..821c517 100644
--- a/src/checksum/Makefile.am
+++ b/src/checksum/Makefile.am
@@ -22,7 +22,7 @@ AM_CPPFLAGS = \
 	-DPLUGINDIR=\"${DESTDIR}${plugindir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 # we keep track of build dependencies in deps and use libs to store the paths
 # to the installed libraries. for executables we use the built files directly
@@ -99,11 +99,18 @@ if USE_CMD
   exes += $(DESTDIR)$(sbindir)/charon-cmd
 endif
 
-if USE_TOOLS
+if USE_SCEPCLIENT
   exes += $(DESTDIR)$(ipsecdir)/scepclient
+endif
+
+if USE_PKI
   exes += $(DESTDIR)$(bindir)/pki
 endif
 
+if USE_SWANCTL
+  exes += $(DESTDIR)$(sbindir)/swanctl
+endif
+
 if USE_ATTR_SQL
   exes += $(DESTDIR)$(ipsecdir)/pool
 endif
diff --git a/src/checksum/Makefile.in b/src/checksum/Makefile.in
index d798d31..697899e 100644
--- a/src/checksum/Makefile.in
+++ b/src/checksum/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -105,10 +105,11 @@ EXTRA_PROGRAMS = checksum_builder$(EXEEXT)
 @USE_CHARON_TRUE at am__append_24 = $(DESTDIR)$(ipsecdir)/charon
 @MONOLITHIC_FALSE@@USE_CHARON_TRUE at am__append_25 = -DC_PLUGINS=\""${c_plugins}\""
 @USE_CMD_TRUE at am__append_26 = $(DESTDIR)$(sbindir)/charon-cmd
- at USE_TOOLS_TRUE@am__append_27 = $(DESTDIR)$(ipsecdir)/scepclient \
- at USE_TOOLS_TRUE@	$(DESTDIR)$(bindir)/pki
- at USE_ATTR_SQL_TRUE@am__append_28 = $(DESTDIR)$(ipsecdir)/pool
- at USE_IMV_ATTESTATION_TRUE@am__append_29 = $(DESTDIR)$(ipsecdir)/attest
+ at USE_SCEPCLIENT_TRUE@am__append_27 = $(DESTDIR)$(ipsecdir)/scepclient
+ at USE_PKI_TRUE@am__append_28 = $(DESTDIR)$(bindir)/pki
+ at USE_SWANCTL_TRUE@am__append_29 = $(DESTDIR)$(sbindir)/swanctl
+ at USE_ATTR_SQL_TRUE@am__append_30 = $(DESTDIR)$(ipsecdir)/pool
+ at USE_IMV_ATTESTATION_TRUE@am__append_31 = $(DESTDIR)$(ipsecdir)/attest
 subdir = src/checksum
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -304,6 +305,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -322,6 +324,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -349,6 +352,7 @@ 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@
@@ -440,6 +444,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -470,7 +475,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan \
 	-DPLUGINDIR=\"${DESTDIR}${plugindir}\" $(am__append_1) \
 	$(am__append_4) $(am__append_15) $(am__append_25)
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 
 # we keep track of build dependencies in deps and use libs to store the paths
@@ -486,7 +491,8 @@ libs = $(DESTDIR)$(ipseclibdir)/libstrongswan.so $(am__append_3) \
 	$(am__append_12) $(am__append_14) $(am__append_17) \
 	$(am__append_19) $(am__append_21) $(am__append_23)
 exes = $(am__append_24) $(am__append_26) $(am__append_27) \
-	$(am__append_28) $(am__append_29)
+	$(am__append_28) $(am__append_29) $(am__append_30) \
+	$(am__append_31)
 all: all-am
 
 .SUFFIXES:
diff --git a/src/conftest/Makefile.am b/src/conftest/Makefile.am
index 900741d..eeb26f2 100644
--- a/src/conftest/Makefile.am
+++ b/src/conftest/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINS=\""${charon_plugins}\""
 
-AM_CFLAGS = -rdynamic
+AM_CFLAGS = $(PLUGIN_CFLAGS)
 
 conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \
 	hooks/hook.h hooks/ike_auth_fill.c hooks/unsort_message.c \
diff --git a/src/conftest/Makefile.in b/src/conftest/Makefile.in
index 453e8f8..edd07b8 100644
--- a/src/conftest/Makefile.in
+++ b/src/conftest/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -250,6 +250,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -268,6 +269,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -295,6 +297,7 @@ 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@
@@ -386,6 +389,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -402,7 +406,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon \
 	-DPLUGINS=\""${charon_plugins}\""
 
-AM_CFLAGS = -rdynamic
+AM_CFLAGS = $(PLUGIN_CFLAGS)
 conftest_SOURCES = conftest.c conftest.h config.c config.h actions.c actions.h \
 	hooks/hook.h hooks/ike_auth_fill.c hooks/unsort_message.c \
 	hooks/add_notify.c hooks/unencrypted_notify.c hooks/ignore_message.c \
diff --git a/src/conftest/README b/src/conftest/README
index 617195d..d37539a 100644
--- a/src/conftest/README
+++ b/src/conftest/README
@@ -304,7 +304,7 @@ Compile time options required depend on the test suite. A minimalistic
 strongSwan build with the OpenSSL crypto backend can be configured with:
 
 ./configure --sysconfdir=/etc --disable-pluto --disable-scripts \
-  --disable-tools --disable-aes --disable-des --disable-md5 \
+  --disable-scepclient --disable-aes --disable-des --disable-md5 \
   --disable-sha1 --disable-sha2 --disable-fips-prf --disable-gmp \
   --disable-pubkey --disable-pgp --disable-dnskey --disable-updown \
   --disable-attr --disable-resolve --enable-openssl --enable-conftest \
diff --git a/src/conftest/config.c b/src/conftest/config.c
index 5aa742d..c83db7e 100644
--- a/src/conftest/config.c
+++ b/src/conftest/config.c
@@ -129,6 +129,7 @@ static ike_cfg_t *load_ike_config(private_config_t *this,
 	else
 	{
 		ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+		ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 	}
 	return ike_cfg;
 }
@@ -180,6 +181,8 @@ static child_cfg_t *load_child_config(private_config_t *this,
 	else
 	{
 		child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+		child_cfg->add_proposal(child_cfg,
+								proposal_create_default_aead(PROTO_ESP));
 	}
 
 	token = settings->get_str(settings, "configs.%s.%s.lts", NULL, config, child);
diff --git a/src/conftest/hooks/add_notify.c b/src/conftest/hooks/add_notify.c
index 9611cad..73a9b1a 100644
--- a/src/conftest/hooks/add_notify.c
+++ b/src/conftest/hooks/add_notify.c
@@ -73,8 +73,7 @@ METHOD(listener_t, message, bool,
 		type = atoi(this->type);
 		if (!type)
 		{
-			type = enum_from_name(notify_type_names, this->type);
-			if (type == -1)
+			if (!enum_from_name(notify_type_names, this->type, &type))
 			{
 				DBG1(DBG_CFG, "unknown notify: '%s', skipped", this->type);
 				return TRUE;
@@ -89,7 +88,7 @@ METHOD(listener_t, message, bool,
 		{
 			data = chunk_clone(chunk_create(this->data, strlen(this->data)));
 		}
-		notify = notify_payload_create_from_protocol_and_type(NOTIFY,
+		notify = notify_payload_create_from_protocol_and_type(PLV2_NOTIFY,
 									this->esp ? PROTO_ESP : PROTO_IKE, type);
 		notify->set_spi(notify, this->spi);
 		if (data.len)
diff --git a/src/conftest/hooks/add_payload.c b/src/conftest/hooks/add_payload.c
index 2903bb2..cb5be1a 100644
--- a/src/conftest/hooks/add_payload.c
+++ b/src/conftest/hooks/add_payload.c
@@ -77,8 +77,7 @@ METHOD(listener_t, message, bool,
 		type = atoi(this->type);
 		if (!type)
 		{
-			type = enum_from_name(payload_type_short_names, this->type);
-			if (type == -1)
+			if (!enum_from_name(payload_type_short_names, this->type, &type))
 			{
 				DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type);
 				return TRUE;
diff --git a/src/conftest/hooks/custom_proposal.c b/src/conftest/hooks/custom_proposal.c
index 38d4286..ee44045 100644
--- a/src/conftest/hooks/custom_proposal.c
+++ b/src/conftest/hooks/custom_proposal.c
@@ -79,8 +79,7 @@ static linked_list_t* load_proposals(private_custom_proposal_t *this,
 			type = strtoul(key, &end, 10);
 			if (end == key || errno)
 			{
-				type = enum_from_name(transform_type_names, key);
-				if (type == -1)
+				if (!enum_from_name(transform_type_names, key, &type))
 				{
 					DBG1(DBG_CFG, "unknown transform: '%s', skipped", key);
 					continue;
@@ -125,7 +124,7 @@ METHOD(listener_t, message, bool,
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == SECURITY_ASSOCIATION)
+			if (payload->get_type(payload) == PLV2_SECURITY_ASSOCIATION)
 			{
 				old = (sa_payload_t*)payload;
 				message->remove_payload_at(message, enumerator);
diff --git a/src/conftest/hooks/force_cookie.c b/src/conftest/hooks/force_cookie.c
index 1b044db..6be516c 100644
--- a/src/conftest/hooks/force_cookie.c
+++ b/src/conftest/hooks/force_cookie.c
@@ -44,7 +44,7 @@ METHOD(listener_t, message, bool,
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == NOTIFY)
+			if (payload->get_type(payload) == PLV2_NOTIFY)
 			{
 				notify_payload_t *notify = (notify_payload_t*)payload;
 				chunk_t data;
diff --git a/src/conftest/hooks/ike_auth_fill.c b/src/conftest/hooks/ike_auth_fill.c
index 09590d4..5cdd5be 100644
--- a/src/conftest/hooks/ike_auth_fill.c
+++ b/src/conftest/hooks/ike_auth_fill.c
@@ -108,7 +108,7 @@ METHOD(listener_t, message, bool,
 			diff = this->bytes - size - CERT_PAYLOAD_HEADER_LENGTH;
 			data = chunk_alloc(diff);
 			memset(data.ptr, 0x12, data.len);
-			pld = cert_payload_create_custom(CERTIFICATE, 201, data);
+			pld = cert_payload_create_custom(PLV2_CERTIFICATE, 201, data);
 			message->add_payload(message, &pld->payload_interface);
 			DBG1(DBG_CFG, "inserting %d dummy bytes certificate payload", diff);
 		}
diff --git a/src/conftest/hooks/log_id.c b/src/conftest/hooks/log_id.c
index 07dd6a4..f47372f 100644
--- a/src/conftest/hooks/log_id.c
+++ b/src/conftest/hooks/log_id.c
@@ -45,8 +45,8 @@ METHOD(listener_t, message, bool,
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == ID_INITIATOR ||
-				payload->get_type(payload) == ID_RESPONDER)
+			if (payload->get_type(payload) == PLV2_ID_INITIATOR ||
+				payload->get_type(payload) == PLV2_ID_RESPONDER)
 			{
 				id_payload = (id_payload_t*)payload;
 				id = id_payload->get_identification(id_payload);
diff --git a/src/conftest/hooks/log_ke.c b/src/conftest/hooks/log_ke.c
index 7104823..66aa4a6 100644
--- a/src/conftest/hooks/log_ke.c
+++ b/src/conftest/hooks/log_ke.c
@@ -43,7 +43,7 @@ METHOD(listener_t, message, bool,
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == KEY_EXCHANGE)
+			if (payload->get_type(payload) == PLV2_KEY_EXCHANGE)
 			{
 				ke = (ke_payload_t*)payload;
 				DBG1(DBG_CFG, "received DH group %N",
diff --git a/src/conftest/hooks/log_proposals.c b/src/conftest/hooks/log_proposals.c
index 347b832..c0d458e 100644
--- a/src/conftest/hooks/log_proposals.c
+++ b/src/conftest/hooks/log_proposals.c
@@ -45,7 +45,7 @@ METHOD(listener_t, message, bool,
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == SECURITY_ASSOCIATION)
+			if (payload->get_type(payload) == PLV2_SECURITY_ASSOCIATION)
 			{
 				sa = (sa_payload_t*)payload;
 				list = sa->get_proposals(sa);
diff --git a/src/conftest/hooks/log_ts.c b/src/conftest/hooks/log_ts.c
index f212efa..79c59b8 100644
--- a/src/conftest/hooks/log_ts.c
+++ b/src/conftest/hooks/log_ts.c
@@ -43,8 +43,8 @@ METHOD(listener_t, message, bool,
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == TRAFFIC_SELECTOR_INITIATOR ||
-				payload->get_type(payload) == TRAFFIC_SELECTOR_RESPONDER)
+			if (payload->get_type(payload) == PLV2_TS_INITIATOR ||
+				payload->get_type(payload) == PLV2_TS_RESPONDER)
 			{
 				ts = (ts_payload_t*)payload;
 				host_t *from, *to;
diff --git a/src/conftest/hooks/pretend_auth.c b/src/conftest/hooks/pretend_auth.c
index 4166afc..54957b0 100644
--- a/src/conftest/hooks/pretend_auth.c
+++ b/src/conftest/hooks/pretend_auth.c
@@ -79,7 +79,7 @@ static void process_init_request(private_pretend_auth_t *this,
 {
 	nonce_payload_t *nonce;
 
-	nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
+	nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
 	if (nonce)
 	{
 		free(this->nonce.ptr);
@@ -98,13 +98,13 @@ static void process_auth_request(private_pretend_auth_t *this,
 	ts_payload_t *tsi, *tsr;
 	linked_list_t *proposals;
 
-	id = (id_payload_t*)message->get_payload(message, ID_RESPONDER);
+	id = (id_payload_t*)message->get_payload(message, PLV2_ID_RESPONDER);
 	if (id)
 	{
 		this->id->destroy(this->id);
 		this->id = id->get_identification(id);
 	}
-	sa = (sa_payload_t*)message->get_payload(message, SECURITY_ASSOCIATION);
+	sa = (sa_payload_t*)message->get_payload(message, PLV2_SECURITY_ASSOCIATION);
 	if (sa)
 	{
 		proposals = sa->get_proposals(sa);
@@ -116,13 +116,13 @@ static void process_auth_request(private_pretend_auth_t *this,
 		proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
 	}
 	tsi = (ts_payload_t*)message->get_payload(message,
-											  TRAFFIC_SELECTOR_INITIATOR);
+											  PLV2_TS_INITIATOR);
 	if (tsi)
 	{
 		this->tsi = tsi->get_traffic_selectors(tsi);
 	}
 	tsr = (ts_payload_t*)message->get_payload(message,
-											  TRAFFIC_SELECTOR_RESPONDER);
+											  PLV2_TS_RESPONDER);
 	if (tsr)
 	{
 		this->tsr = tsr->get_traffic_selectors(tsr);
@@ -154,7 +154,7 @@ static void build_certs(private_pretend_auth_t *this,
 	cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
 	if (cert)
 	{
-		payload = cert_payload_create_from_cert(CERTIFICATE, cert);
+		payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 		if (payload)
 		{
 			DBG1(DBG_IKE, "pretending end entity cert \"%Y\"",
@@ -167,7 +167,7 @@ static void build_certs(private_pretend_auth_t *this,
 	{
 		if (type == AUTH_RULE_IM_CERT)
 		{
-			payload = cert_payload_create_from_cert(CERTIFICATE, cert);
+			payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 			if (payload)
 			{
 				DBG1(DBG_IKE, "pretending issuer cert \"%Y\"",
@@ -276,7 +276,7 @@ static void process_auth_response(private_pretend_auth_t *this,
 	{
 		notify_payload_t *notify = (notify_payload_t*)payload;
 
-		if (payload->get_type(payload) != NOTIFY ||
+		if (payload->get_type(payload) != PLV2_NOTIFY ||
 			notify->get_notify_type(notify) != AUTHENTICATION_FAILED)
 		{
 			DBG1(DBG_CFG, "no %N notify found, disabling AUTH pretending",
@@ -295,7 +295,7 @@ static void process_auth_response(private_pretend_auth_t *this,
 		return;
 	}
 	message->add_payload(message, (payload_t*)
-				id_payload_create_from_identification(ID_RESPONDER, this->id));
+				id_payload_create_from_identification(PLV2_ID_RESPONDER, this->id));
 	if (this->proposal)
 	{
 		message->add_payload(message, (payload_t*)
diff --git a/src/conftest/hooks/rebuild_auth.c b/src/conftest/hooks/rebuild_auth.c
index b7e6f22..bc2f000 100644
--- a/src/conftest/hooks/rebuild_auth.c
+++ b/src/conftest/hooks/rebuild_auth.c
@@ -70,7 +70,7 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
 	u_int32_t *lenpos;
 
 	payload = message->get_payload(message,
-					message->get_request(message) ? ID_INITIATOR : ID_RESPONDER);
+					message->get_request(message) ? PLV2_ID_INITIATOR : PLV2_ID_RESPONDER);
 	if (!payload)
 	{
 		DBG1(DBG_CFG, "ID payload not found to rebuild AUTH");
@@ -160,7 +160,7 @@ static bool rebuild_auth(private_rebuild_auth_t *this, ike_sa_t *ike_sa,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == AUTHENTICATION)
+		if (payload->get_type(payload) == PLV2_AUTH)
 		{
 			message->remove_payload_at(message, enumerator);
 			payload->destroy(payload);
@@ -191,7 +191,7 @@ METHOD(listener_t, message, bool,
 			{
 				nonce_payload_t *nonce;
 
-				nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
+				nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
 				if (nonce)
 				{
 					free(this->nonce.ptr);
diff --git a/src/conftest/hooks/set_critical.c b/src/conftest/hooks/set_critical.c
index 8ec84e1..15c313c 100644
--- a/src/conftest/hooks/set_critical.c
+++ b/src/conftest/hooks/set_critical.c
@@ -65,8 +65,7 @@ METHOD(listener_t, message, bool,
 			type = atoi(name);
 			if (!type)
 			{
-				type = enum_from_name(payload_type_short_names, name);
-				if (type == -1)
+				if (!enum_from_name(payload_type_short_names, name, &type))
 				{
 					DBG1(DBG_CFG, "invalid payload name '%s'", name);
 					break;
diff --git a/src/conftest/hooks/set_length.c b/src/conftest/hooks/set_length.c
index c1a867a..b1a1a47 100644
--- a/src/conftest/hooks/set_length.c
+++ b/src/conftest/hooks/set_length.c
@@ -63,8 +63,7 @@ METHOD(listener_t, message, bool,
 		type = atoi(this->type);
 		if (!type)
 		{
-			type = enum_from_name(payload_type_short_names, this->type);
-			if (type == -1)
+			if (!enum_from_name(payload_type_short_names, this->type, &type))
 			{
 				DBG1(DBG_CFG, "unknown payload: '%s', skipped", this->type);
 				return TRUE;
diff --git a/src/conftest/hooks/set_proposal_number.c b/src/conftest/hooks/set_proposal_number.c
index 0cc3cfc..4e572d6 100644
--- a/src/conftest/hooks/set_proposal_number.c
+++ b/src/conftest/hooks/set_proposal_number.c
@@ -85,7 +85,7 @@ METHOD(listener_t, message, bool,
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == SECURITY_ASSOCIATION)
+			if (payload->get_type(payload) == PLV2_SECURITY_ASSOCIATION)
 			{
 				sa = (sa_payload_t*)payload;
 				list = sa->get_proposals(sa);
diff --git a/src/conftest/hooks/set_reserved.c b/src/conftest/hooks/set_reserved.c
index d1a4a97..488e8df 100644
--- a/src/conftest/hooks/set_reserved.c
+++ b/src/conftest/hooks/set_reserved.c
@@ -55,7 +55,7 @@ static void set_bit(private_set_reserved_t *this, message_t *message,
 	payload_t *payload;
 	bool *bit;
 
-	if (type == HEADER)
+	if (type == PL_HEADER)
 	{
 		message->set_reserved_header_bit(message, nr);
 		DBG1(DBG_CFG, "setting reserved bit %d of %N",
@@ -91,7 +91,7 @@ static void set_byte(private_set_reserved_t *this, message_t *message,
 	payload_t *payload;
 	u_int8_t *byte;
 
-	if (type == TRANSFORM_SUBSTRUCTURE || type == PROPOSAL_SUBSTRUCTURE)
+	if (type == PLV2_TRANSFORM_SUBSTRUCTURE || type == PLV2_PROPOSAL_SUBSTRUCTURE)
 	{
 		enumerator_t *transforms, *proposals;
 		transform_substructure_t *transform;
@@ -101,13 +101,13 @@ static void set_byte(private_set_reserved_t *this, message_t *message,
 		payloads = message->create_payload_enumerator(message);
 		while (payloads->enumerate(payloads, &payload))
 		{
-			if (payload->get_type(payload) == SECURITY_ASSOCIATION)
+			if (payload->get_type(payload) == PLV2_SECURITY_ASSOCIATION)
 			{
 				sa = (sa_payload_t*)payload;
 				proposals = sa->create_substructure_enumerator(sa);
 				while (proposals->enumerate(proposals, &proposal))
 				{
-					if (type == PROPOSAL_SUBSTRUCTURE)
+					if (type == PLV2_PROPOSAL_SUBSTRUCTURE)
 					{
 						byte = payload_get_field(&proposal->payload_interface,
 												 RESERVED_BYTE, nr);
@@ -118,7 +118,7 @@ static void set_byte(private_set_reserved_t *this, message_t *message,
 							*byte = byteval;
 						}
 					}
-					else if (type == TRANSFORM_SUBSTRUCTURE)
+					else if (type == PLV2_TRANSFORM_SUBSTRUCTURE)
 					{
 						transforms = proposal->create_substructure_enumerator(
 																	proposal);
@@ -181,8 +181,7 @@ METHOD(listener_t, message, bool,
 			type = atoi(name);
 			if (!type)
 			{
-				type = enum_from_name(payload_type_short_names, name);
-				if (type == -1)
+				if (!enum_from_name(payload_type_short_names, name, &type))
 				{
 					DBG1(DBG_CFG, "invalid payload name '%s'", name);
 					break;
diff --git a/src/conftest/hooks/unencrypted_notify.c b/src/conftest/hooks/unencrypted_notify.c
index f4c3572..2a74985 100644
--- a/src/conftest/hooks/unencrypted_notify.c
+++ b/src/conftest/hooks/unencrypted_notify.c
@@ -68,8 +68,7 @@ METHOD(listener_t, ike_updown, bool,
 		type = atoi(this->type);
 		if (!type)
 		{
-			type = enum_from_name(notify_type_names, this->type);
-			if (type == -1)
+			if (!enum_from_name(notify_type_names, this->type, &type))
 			{
 				DBG1(DBG_CFG, "unknown notify: '%s', skipped", this->type);
 				return TRUE;
@@ -84,7 +83,7 @@ METHOD(listener_t, ike_updown, bool,
 		{
 			data = chunk_clone(chunk_create(this->data, strlen(this->data)));
 		}
-		notify = notify_payload_create_from_protocol_and_type(NOTIFY,
+		notify = notify_payload_create_from_protocol_and_type(PLV2_NOTIFY,
 									this->esp ? PROTO_ESP : PROTO_IKE, type);
 		notify->set_spi(notify, this->spi);
 		if (data.len)
diff --git a/src/conftest/hooks/unsort_message.c b/src/conftest/hooks/unsort_message.c
index 1b2b302..399d293 100644
--- a/src/conftest/hooks/unsort_message.c
+++ b/src/conftest/hooks/unsort_message.c
@@ -69,8 +69,7 @@ METHOD(listener_t, message, bool,
 		order = enumerator_create_token(this->order, ", ", " ");
 		while (order->enumerate(order, &name))
 		{
-			type = enum_from_name(payload_type_short_names, name);
-			if (type != -1)
+			if (enum_from_name(payload_type_short_names, name, &type))
 			{
 				enumerator = list->create_enumerator(list);
 				while (enumerator->enumerate(enumerator, &payload))
diff --git a/src/dumm/Makefile.in b/src/dumm/Makefile.in
index 2f7b2ea..fd4a5db 100644
--- a/src/dumm/Makefile.in
+++ b/src/dumm/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -271,6 +271,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -289,6 +290,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -316,6 +318,7 @@ 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@
@@ -407,6 +410,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/dumm/ext/dumm.c b/src/dumm/ext/dumm.c
index 03ecbe4..d791c08 100644
--- a/src/dumm/ext/dumm.c
+++ b/src/dumm/ext/dumm.c
@@ -32,6 +32,8 @@
 #undef PACKAGE_URL
 /* avoid redefintiion of snprintf etc. */
 #define RUBY_DONT_SUBST
+/* undef our _GNU_SOURCE, as it gets redefined by <ruby.h> */
+#undef _GNU_SOURCE
 #include <ruby.h>
 
 static dumm_t *dumm;
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
index f5277e3..ed755cb 100644
--- a/src/include/Makefile.in
+++ b/src/include/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -179,6 +179,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -197,6 +198,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -224,6 +226,7 @@ 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@
@@ -315,6 +318,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/ipsec/Makefile.in b/src/ipsec/Makefile.in
index 545123b..baa4532 100644
--- a/src/ipsec/Makefile.in
+++ b/src/ipsec/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -213,6 +213,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -231,6 +232,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -258,6 +260,7 @@ 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@
@@ -349,6 +352,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/ipsec/_ipsec.8 b/src/ipsec/_ipsec.8
index 1701060..3dcb03a 100644
--- a/src/ipsec/_ipsec.8
+++ b/src/ipsec/_ipsec.8
@@ -1,4 +1,4 @@
-.TH IPSEC 8 "2013-10-29" "5.2.0dr1" "strongSwan"
+.TH IPSEC 8 "2013-10-29" "5.2.0" "strongSwan"
 .
 .SH NAME
 .
diff --git a/src/ipsec/_ipsec.in b/src/ipsec/_ipsec.in
index 6163218..e6725d0 100644
--- a/src/ipsec/_ipsec.in
+++ b/src/ipsec/_ipsec.in
@@ -1,7 +1,7 @@
 #! @IPSEC_SHELL@
 # prefix command to run stuff from our programs directory
 # Copyright (C) 1998-2002  Henry Spencer.
-# Copyright (C) 2006 Andreas Steffen
+# Copyright (C) 2006-2014 Andreas Steffen
 # Copyright (C) 2006 Martin Willi
 #
 # This program is free software; you can redistribute it and/or modify it
@@ -317,6 +317,10 @@ pki)
 	shift
 	exec $IPSEC_BINDIR/pki "$@"
 	;;
+aikgen)
+	shift
+	exec $IPSEC_BINDIR/aikgen "$@"
+	;;
 version|--version)
 	printf "$OS_NAME $IPSEC_NAME $IPSEC_VERSION\n"
 	printf "$IPSEC_DISTRO\n"
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index cc52209..a28b459 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -7,7 +7,6 @@ bus/bus.c bus/bus.h \
 bus/listeners/listener.h \
 bus/listeners/logger.h \
 bus/listeners/file_logger.c bus/listeners/file_logger.h \
-bus/listeners/sys_logger.c bus/listeners/sys_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 \
@@ -123,6 +122,9 @@ sa/ikev1/tasks/mode_config.c sa/ikev1/tasks/mode_config.h \
 processing/jobs/dpd_timeout_job.c processing/jobs/dpd_timeout_job.h \
 processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
 
+libcharon_la_SOURCES += \
+    bus/listeners/sys_logger.c bus/listeners/sys_logger.h
+
 LOCAL_SRC_FILES := $(filter %.c,$(libcharon_la_SOURCES))
 
 # adding the plugin source files
@@ -199,6 +201,7 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtls/
 LOCAL_SRC_FILES += $(addprefix ../libtls/, \
 		tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
 		tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
+		tls_aead_expl.c tls_aead_impl.c tls_aead_null.c tls_aead.c \
 		tls_server.c tls.c \
 	)
 endif
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index df58eaa..e81c424 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -5,7 +5,6 @@ bus/bus.c bus/bus.h \
 bus/listeners/listener.h \
 bus/listeners/logger.h \
 bus/listeners/file_logger.c bus/listeners/file_logger.h \
-bus/listeners/sys_logger.c bus/listeners/sys_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 \
@@ -125,6 +124,10 @@ processing/jobs/dpd_timeout_job.c processing/jobs/dpd_timeout_job.h \
 processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
 endif
 
+if USE_SYSLOG
+  libcharon_la_SOURCES += \
+    bus/listeners/sys_logger.c bus/listeners/sys_logger.h
+endif
 
 daemon.lo :		$(top_builddir)/config.status
 
@@ -144,6 +147,10 @@ libcharon_la_LIBADD = \
   $(top_builddir)/src/libhydra/libhydra.la \
   -lm $(PTHREADLIB) $(DLLIB) $(SOCKLIB)
 
+if USE_WINDOWS
+  libcharon_la_LIBADD += -lws2_32
+endif
+
 EXTRA_DIST = Android.mk
 
 # compile options
@@ -188,6 +195,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_SOCKET_WIN
+  SUBDIRS += plugins/socket_win
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/socket_win/libstrongswan-socket-win.la
+endif
+endif
+
 if USE_FARP
   SUBDIRS += plugins/farp
 if MONOLITHIC
@@ -202,6 +216,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_VICI
+  SUBDIRS += plugins/vici
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/vici/libstrongswan-vici.la
+endif
+endif
+
 if USE_SMP
   SUBDIRS += plugins/smp
 if MONOLITHIC
@@ -468,6 +489,20 @@ if MONOLITHIC
 endif
 endif
 
+if USE_KERNEL_WFP
+  SUBDIRS += plugins/kernel_wfp
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/kernel_wfp/libstrongswan-kernel-wfp.la
+endif
+endif
+
+if USE_KERNEL_IPH
+  SUBDIRS += plugins/kernel_iph
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/kernel_iph/libstrongswan-kernel-iph.la
+endif
+endif
+
 if USE_WHITELIST
   SUBDIRS += plugins/whitelist
 if MONOLITHIC
diff --git a/src/libcharon/Makefile.in b/src/libcharon/Makefile.in
index b300df3..002da51 100644
--- a/src/libcharon/Makefile.in
+++ b/src/libcharon/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -124,132 +124,144 @@ host_triplet = @host@
 @USE_IKEV1_TRUE at processing/jobs/dpd_timeout_job.c processing/jobs/dpd_timeout_job.h \
 @USE_IKEV1_TRUE at processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
 
+ at USE_SYSLOG_TRUE@am__append_3 = \
+ at USE_SYSLOG_TRUE@    bus/listeners/sys_logger.c bus/listeners/sys_logger.h
+
+ at USE_WINDOWS_TRUE@am__append_4 = -lws2_32
 
 # compile options
 #################
- at USE_ME_TRUE@am__append_3 = encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
+ at USE_ME_TRUE@am__append_5 = encoding/payloads/endpoint_notify.c encoding/payloads/endpoint_notify.h \
 @USE_ME_TRUE@    processing/jobs/initiate_mediation_job.c processing/jobs/initiate_mediation_job.h \
 @USE_ME_TRUE@    processing/jobs/mediation_job.c processing/jobs/mediation_job.h \
 @USE_ME_TRUE@    sa/ikev2/connect_manager.c sa/ikev2/connect_manager.h \
 @USE_ME_TRUE@    sa/ikev2/mediation_manager.c sa/ikev2/mediation_manager.h \
 @USE_ME_TRUE@    sa/ikev2/tasks/ike_me.c sa/ikev2/tasks/ike_me.h
 
- at USE_LOAD_TESTER_TRUE@am__append_4 = plugins/load_tester
- at MONOLITHIC_TRUE@@USE_LOAD_TESTER_TRUE at am__append_5 = plugins/load_tester/libstrongswan-load-tester.la
- at USE_SOCKET_DEFAULT_TRUE@am__append_6 = plugins/socket_default
- at MONOLITHIC_TRUE@@USE_SOCKET_DEFAULT_TRUE at am__append_7 = plugins/socket_default/libstrongswan-socket-default.la
- at USE_SOCKET_DYNAMIC_TRUE@am__append_8 = plugins/socket_dynamic
- at MONOLITHIC_TRUE@@USE_SOCKET_DYNAMIC_TRUE at am__append_9 = plugins/socket_dynamic/libstrongswan-socket-dynamic.la
- at USE_FARP_TRUE@am__append_10 = plugins/farp
- at MONOLITHIC_TRUE@@USE_FARP_TRUE at am__append_11 = plugins/farp/libstrongswan-farp.la
- at USE_STROKE_TRUE@am__append_12 = plugins/stroke
- at MONOLITHIC_TRUE@@USE_STROKE_TRUE at am__append_13 = plugins/stroke/libstrongswan-stroke.la
- at USE_SMP_TRUE@am__append_14 = plugins/smp
- at MONOLITHIC_TRUE@@USE_SMP_TRUE at am__append_15 = plugins/smp/libstrongswan-smp.la
- at USE_SQL_TRUE@am__append_16 = plugins/sql
- at MONOLITHIC_TRUE@@USE_SQL_TRUE at am__append_17 = plugins/sql/libstrongswan-sql.la
- at USE_DNSCERT_TRUE@am__append_18 = plugins/dnscert
- at MONOLITHIC_TRUE@@USE_DNSCERT_TRUE at am__append_19 = plugins/dnscert/libstrongswan-dnscert.la
- at USE_IPSECKEY_TRUE@am__append_20 = plugins/ipseckey
- at MONOLITHIC_TRUE@@USE_IPSECKEY_TRUE at am__append_21 = plugins/ipseckey/libstrongswan-ipseckey.la
- at USE_UPDOWN_TRUE@am__append_22 = plugins/updown
- at MONOLITHIC_TRUE@@USE_UPDOWN_TRUE at am__append_23 = plugins/updown/libstrongswan-updown.la
- at USE_EAP_IDENTITY_TRUE@am__append_24 = plugins/eap_identity
- at MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE at am__append_25 = plugins/eap_identity/libstrongswan-eap-identity.la
- at USE_EAP_SIM_TRUE@am__append_26 = plugins/eap_sim
- at MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE at am__append_27 = plugins/eap_sim/libstrongswan-eap-sim.la
- at USE_EAP_SIM_FILE_TRUE@am__append_28 = plugins/eap_sim_file
- at MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE at am__append_29 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
- at USE_EAP_SIM_PCSC_TRUE@am__append_30 = plugins/eap_sim_pcsc
- at MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE at am__append_31 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
- at USE_EAP_SIMAKA_SQL_TRUE@am__append_32 = plugins/eap_simaka_sql
- at MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE at am__append_33 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
- at USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_34 = plugins/eap_simaka_pseudonym
- at MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE at am__append_35 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
- at USE_EAP_SIMAKA_REAUTH_TRUE@am__append_36 = plugins/eap_simaka_reauth
- at MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE at am__append_37 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
- at USE_EAP_AKA_TRUE@am__append_38 = plugins/eap_aka
- at MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE at am__append_39 = plugins/eap_aka/libstrongswan-eap-aka.la
- at USE_EAP_AKA_3GPP2_TRUE@am__append_40 = plugins/eap_aka_3gpp2
- at MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE at am__append_41 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
- at MONOLITHIC_TRUE@@USE_SIMAKA_TRUE at am__append_42 = $(top_builddir)/src/libsimaka/libsimaka.la
- at USE_EAP_MD5_TRUE@am__append_43 = plugins/eap_md5
- at MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE at am__append_44 = plugins/eap_md5/libstrongswan-eap-md5.la
- at USE_EAP_GTC_TRUE@am__append_45 = plugins/eap_gtc
- at MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE at am__append_46 = plugins/eap_gtc/libstrongswan-eap-gtc.la
- at USE_EAP_MSCHAPV2_TRUE@am__append_47 = plugins/eap_mschapv2
- at MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE at am__append_48 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
- at USE_EAP_DYNAMIC_TRUE@am__append_49 = plugins/eap_dynamic
- at MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE at am__append_50 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la
- at USE_EAP_RADIUS_TRUE@am__append_51 = plugins/eap_radius
- at MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE at am__append_52 = plugins/eap_radius/libstrongswan-eap-radius.la
- at USE_EAP_TLS_TRUE@am__append_53 = plugins/eap_tls
- at MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE at am__append_54 = plugins/eap_tls/libstrongswan-eap-tls.la
- at USE_EAP_TTLS_TRUE@am__append_55 = plugins/eap_ttls
- at MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE at am__append_56 = plugins/eap_ttls/libstrongswan-eap-ttls.la
- at USE_EAP_PEAP_TRUE@am__append_57 = plugins/eap_peap
- at MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE at am__append_58 = plugins/eap_peap/libstrongswan-eap-peap.la
- at USE_EAP_TNC_TRUE@am__append_59 = plugins/eap_tnc
- at MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE at am__append_60 = plugins/eap_tnc/libstrongswan-eap-tnc.la
- at MONOLITHIC_TRUE@@USE_TLS_TRUE at am__append_61 = $(top_builddir)/src/libtls/libtls.la
- at MONOLITHIC_TRUE@@USE_RADIUS_TRUE at am__append_62 = $(top_builddir)/src/libradius/libradius.la
- at USE_TNC_IFMAP_TRUE@am__append_63 = plugins/tnc_ifmap
- at MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE at am__append_64 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
- at USE_TNC_PDP_TRUE@am__append_65 = plugins/tnc_pdp
- at MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE at am__append_66 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la
- at MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE at am__append_67 = $(top_builddir)/src/libtnccs/libtnccs.la
- at USE_MEDSRV_TRUE@am__append_68 = plugins/medsrv
- at MONOLITHIC_TRUE@@USE_MEDSRV_TRUE at am__append_69 = plugins/medsrv/libstrongswan-medsrv.la
- at USE_MEDCLI_TRUE@am__append_70 = plugins/medcli
- at MONOLITHIC_TRUE@@USE_MEDCLI_TRUE at am__append_71 = plugins/medcli/libstrongswan-medcli.la
- at USE_DHCP_TRUE@am__append_72 = plugins/dhcp
- at MONOLITHIC_TRUE@@USE_DHCP_TRUE at am__append_73 = plugins/dhcp/libstrongswan-dhcp.la
- at USE_OSX_ATTR_TRUE@am__append_74 = plugins/osx_attr
- at MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE at am__append_75 = plugins/osx_attr/libstrongswan-osx-attr.la
- at USE_ANDROID_DNS_TRUE@am__append_76 = plugins/android_dns
- at MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE at am__append_77 = plugins/android_dns/libstrongswan-android-dns.la
- at USE_ANDROID_LOG_TRUE@am__append_78 = plugins/android_log
- at MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE at am__append_79 = plugins/android_log/libstrongswan-android-log.la
- at USE_MAEMO_TRUE@am__append_80 = plugins/maemo
- at MONOLITHIC_TRUE@@USE_MAEMO_TRUE at am__append_81 = plugins/maemo/libstrongswan-maemo.la
- at USE_HA_TRUE@am__append_82 = plugins/ha
- at MONOLITHIC_TRUE@@USE_HA_TRUE at am__append_83 = plugins/ha/libstrongswan-ha.la
- at USE_KERNEL_LIBIPSEC_TRUE@am__append_84 = plugins/kernel_libipsec
- at MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE at am__append_85 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
- at USE_WHITELIST_TRUE@am__append_86 = plugins/whitelist
- at MONOLITHIC_TRUE@@USE_WHITELIST_TRUE at am__append_87 = plugins/whitelist/libstrongswan-whitelist.la
- at USE_LOOKIP_TRUE@am__append_88 = plugins/lookip
- at MONOLITHIC_TRUE@@USE_LOOKIP_TRUE at am__append_89 = plugins/lookip/libstrongswan-lookip.la
- at USE_ERROR_NOTIFY_TRUE@am__append_90 = plugins/error_notify
- at MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE at am__append_91 = plugins/error_notify/libstrongswan-error-notify.la
- at USE_CERTEXPIRE_TRUE@am__append_92 = plugins/certexpire
- at MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE at am__append_93 = plugins/certexpire/libstrongswan-certexpire.la
- at USE_SYSTIME_FIX_TRUE@am__append_94 = plugins/systime_fix
- at MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE at am__append_95 = plugins/systime_fix/libstrongswan-systime-fix.la
- at USE_LED_TRUE@am__append_96 = plugins/led
- at MONOLITHIC_TRUE@@USE_LED_TRUE at am__append_97 = plugins/led/libstrongswan-led.la
- at USE_DUPLICHECK_TRUE@am__append_98 = plugins/duplicheck
- at MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE at am__append_99 = plugins/duplicheck/libstrongswan-duplicheck.la
- at USE_COUPLING_TRUE@am__append_100 = plugins/coupling
- at MONOLITHIC_TRUE@@USE_COUPLING_TRUE at am__append_101 = plugins/coupling/libstrongswan-coupling.la
- at USE_RADATTR_TRUE@am__append_102 = plugins/radattr
- at MONOLITHIC_TRUE@@USE_RADATTR_TRUE at am__append_103 = plugins/radattr/libstrongswan-radattr.la
- at USE_UCI_TRUE@am__append_104 = plugins/uci
- at MONOLITHIC_TRUE@@USE_UCI_TRUE at am__append_105 = plugins/uci/libstrongswan-uci.la
- at USE_ADDRBLOCK_TRUE@am__append_106 = plugins/addrblock
- at MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE at am__append_107 = plugins/addrblock/libstrongswan-addrblock.la
- at USE_UNITY_TRUE@am__append_108 = plugins/unity
- at MONOLITHIC_TRUE@@USE_UNITY_TRUE at am__append_109 = plugins/unity/libstrongswan-unity.la
- at USE_UNIT_TESTS_TRUE@am__append_110 = plugins/unit_tester
- at MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE at am__append_111 = plugins/unit_tester/libstrongswan-unit-tester.la
- at USE_XAUTH_GENERIC_TRUE@am__append_112 = plugins/xauth_generic
- at MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE at am__append_113 = plugins/xauth_generic/libstrongswan-xauth-generic.la
- at USE_XAUTH_EAP_TRUE@am__append_114 = plugins/xauth_eap
- at MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE at am__append_115 = plugins/xauth_eap/libstrongswan-xauth-eap.la
- at USE_XAUTH_PAM_TRUE@am__append_116 = plugins/xauth_pam
- at MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE at am__append_117 = plugins/xauth_pam/libstrongswan-xauth-pam.la
- at USE_XAUTH_NOAUTH_TRUE@am__append_118 = plugins/xauth_noauth
- at MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE at am__append_119 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
+ at USE_LOAD_TESTER_TRUE@am__append_6 = plugins/load_tester
+ at MONOLITHIC_TRUE@@USE_LOAD_TESTER_TRUE at am__append_7 = plugins/load_tester/libstrongswan-load-tester.la
+ at USE_SOCKET_DEFAULT_TRUE@am__append_8 = plugins/socket_default
+ at MONOLITHIC_TRUE@@USE_SOCKET_DEFAULT_TRUE at am__append_9 = plugins/socket_default/libstrongswan-socket-default.la
+ at USE_SOCKET_DYNAMIC_TRUE@am__append_10 = plugins/socket_dynamic
+ at MONOLITHIC_TRUE@@USE_SOCKET_DYNAMIC_TRUE at am__append_11 = plugins/socket_dynamic/libstrongswan-socket-dynamic.la
+ at USE_SOCKET_WIN_TRUE@am__append_12 = plugins/socket_win
+ at MONOLITHIC_TRUE@@USE_SOCKET_WIN_TRUE at am__append_13 = plugins/socket_win/libstrongswan-socket-win.la
+ at USE_FARP_TRUE@am__append_14 = plugins/farp
+ at MONOLITHIC_TRUE@@USE_FARP_TRUE at am__append_15 = plugins/farp/libstrongswan-farp.la
+ at USE_STROKE_TRUE@am__append_16 = plugins/stroke
+ at MONOLITHIC_TRUE@@USE_STROKE_TRUE at am__append_17 = plugins/stroke/libstrongswan-stroke.la
+ at USE_VICI_TRUE@am__append_18 = plugins/vici
+ at MONOLITHIC_TRUE@@USE_VICI_TRUE at am__append_19 = plugins/vici/libstrongswan-vici.la
+ at USE_SMP_TRUE@am__append_20 = plugins/smp
+ at MONOLITHIC_TRUE@@USE_SMP_TRUE at am__append_21 = plugins/smp/libstrongswan-smp.la
+ at USE_SQL_TRUE@am__append_22 = plugins/sql
+ at MONOLITHIC_TRUE@@USE_SQL_TRUE at am__append_23 = plugins/sql/libstrongswan-sql.la
+ at USE_DNSCERT_TRUE@am__append_24 = plugins/dnscert
+ at MONOLITHIC_TRUE@@USE_DNSCERT_TRUE at am__append_25 = plugins/dnscert/libstrongswan-dnscert.la
+ at USE_IPSECKEY_TRUE@am__append_26 = plugins/ipseckey
+ at MONOLITHIC_TRUE@@USE_IPSECKEY_TRUE at am__append_27 = plugins/ipseckey/libstrongswan-ipseckey.la
+ at USE_UPDOWN_TRUE@am__append_28 = plugins/updown
+ at MONOLITHIC_TRUE@@USE_UPDOWN_TRUE at am__append_29 = plugins/updown/libstrongswan-updown.la
+ at USE_EAP_IDENTITY_TRUE@am__append_30 = plugins/eap_identity
+ at MONOLITHIC_TRUE@@USE_EAP_IDENTITY_TRUE at am__append_31 = plugins/eap_identity/libstrongswan-eap-identity.la
+ at USE_EAP_SIM_TRUE@am__append_32 = plugins/eap_sim
+ at MONOLITHIC_TRUE@@USE_EAP_SIM_TRUE at am__append_33 = plugins/eap_sim/libstrongswan-eap-sim.la
+ at USE_EAP_SIM_FILE_TRUE@am__append_34 = plugins/eap_sim_file
+ at MONOLITHIC_TRUE@@USE_EAP_SIM_FILE_TRUE at am__append_35 = plugins/eap_sim_file/libstrongswan-eap-sim-file.la
+ at USE_EAP_SIM_PCSC_TRUE@am__append_36 = plugins/eap_sim_pcsc
+ at MONOLITHIC_TRUE@@USE_EAP_SIM_PCSC_TRUE at am__append_37 = plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
+ at USE_EAP_SIMAKA_SQL_TRUE@am__append_38 = plugins/eap_simaka_sql
+ at MONOLITHIC_TRUE@@USE_EAP_SIMAKA_SQL_TRUE at am__append_39 = plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
+ at USE_EAP_SIMAKA_PSEUDONYM_TRUE@am__append_40 = plugins/eap_simaka_pseudonym
+ at MONOLITHIC_TRUE@@USE_EAP_SIMAKA_PSEUDONYM_TRUE at am__append_41 = plugins/eap_simaka_pseudonym/libstrongswan-eap-simaka-pseudonym.la
+ at USE_EAP_SIMAKA_REAUTH_TRUE@am__append_42 = plugins/eap_simaka_reauth
+ at MONOLITHIC_TRUE@@USE_EAP_SIMAKA_REAUTH_TRUE at am__append_43 = plugins/eap_simaka_reauth/libstrongswan-eap-simaka-reauth.la
+ at USE_EAP_AKA_TRUE@am__append_44 = plugins/eap_aka
+ at MONOLITHIC_TRUE@@USE_EAP_AKA_TRUE at am__append_45 = plugins/eap_aka/libstrongswan-eap-aka.la
+ at USE_EAP_AKA_3GPP2_TRUE@am__append_46 = plugins/eap_aka_3gpp2
+ at MONOLITHIC_TRUE@@USE_EAP_AKA_3GPP2_TRUE at am__append_47 = plugins/eap_aka_3gpp2/libstrongswan-eap-aka-3gpp2.la
+ at MONOLITHIC_TRUE@@USE_SIMAKA_TRUE at am__append_48 = $(top_builddir)/src/libsimaka/libsimaka.la
+ at USE_EAP_MD5_TRUE@am__append_49 = plugins/eap_md5
+ at MONOLITHIC_TRUE@@USE_EAP_MD5_TRUE at am__append_50 = plugins/eap_md5/libstrongswan-eap-md5.la
+ at USE_EAP_GTC_TRUE@am__append_51 = plugins/eap_gtc
+ at MONOLITHIC_TRUE@@USE_EAP_GTC_TRUE at am__append_52 = plugins/eap_gtc/libstrongswan-eap-gtc.la
+ at USE_EAP_MSCHAPV2_TRUE@am__append_53 = plugins/eap_mschapv2
+ at MONOLITHIC_TRUE@@USE_EAP_MSCHAPV2_TRUE at am__append_54 = plugins/eap_mschapv2/libstrongswan-eap-mschapv2.la
+ at USE_EAP_DYNAMIC_TRUE@am__append_55 = plugins/eap_dynamic
+ at MONOLITHIC_TRUE@@USE_EAP_DYNAMIC_TRUE at am__append_56 = plugins/eap_dynamic/libstrongswan-eap-dynamic.la
+ at USE_EAP_RADIUS_TRUE@am__append_57 = plugins/eap_radius
+ at MONOLITHIC_TRUE@@USE_EAP_RADIUS_TRUE at am__append_58 = plugins/eap_radius/libstrongswan-eap-radius.la
+ at USE_EAP_TLS_TRUE@am__append_59 = plugins/eap_tls
+ at MONOLITHIC_TRUE@@USE_EAP_TLS_TRUE at am__append_60 = plugins/eap_tls/libstrongswan-eap-tls.la
+ at USE_EAP_TTLS_TRUE@am__append_61 = plugins/eap_ttls
+ at MONOLITHIC_TRUE@@USE_EAP_TTLS_TRUE at am__append_62 = plugins/eap_ttls/libstrongswan-eap-ttls.la
+ at USE_EAP_PEAP_TRUE@am__append_63 = plugins/eap_peap
+ at MONOLITHIC_TRUE@@USE_EAP_PEAP_TRUE at am__append_64 = plugins/eap_peap/libstrongswan-eap-peap.la
+ at USE_EAP_TNC_TRUE@am__append_65 = plugins/eap_tnc
+ at MONOLITHIC_TRUE@@USE_EAP_TNC_TRUE at am__append_66 = plugins/eap_tnc/libstrongswan-eap-tnc.la
+ at MONOLITHIC_TRUE@@USE_TLS_TRUE at am__append_67 = $(top_builddir)/src/libtls/libtls.la
+ at MONOLITHIC_TRUE@@USE_RADIUS_TRUE at am__append_68 = $(top_builddir)/src/libradius/libradius.la
+ at USE_TNC_IFMAP_TRUE@am__append_69 = plugins/tnc_ifmap
+ at MONOLITHIC_TRUE@@USE_TNC_IFMAP_TRUE at am__append_70 = plugins/tnc_ifmap/libstrongswan-tnc-ifmap.la
+ at USE_TNC_PDP_TRUE@am__append_71 = plugins/tnc_pdp
+ at MONOLITHIC_TRUE@@USE_TNC_PDP_TRUE at am__append_72 = plugins/tnc_pdp/libstrongswan-tnc-pdp.la
+ at MONOLITHIC_TRUE@@USE_LIBTNCCS_TRUE at am__append_73 = $(top_builddir)/src/libtnccs/libtnccs.la
+ at USE_MEDSRV_TRUE@am__append_74 = plugins/medsrv
+ at MONOLITHIC_TRUE@@USE_MEDSRV_TRUE at am__append_75 = plugins/medsrv/libstrongswan-medsrv.la
+ at USE_MEDCLI_TRUE@am__append_76 = plugins/medcli
+ at MONOLITHIC_TRUE@@USE_MEDCLI_TRUE at am__append_77 = plugins/medcli/libstrongswan-medcli.la
+ at USE_DHCP_TRUE@am__append_78 = plugins/dhcp
+ at MONOLITHIC_TRUE@@USE_DHCP_TRUE at am__append_79 = plugins/dhcp/libstrongswan-dhcp.la
+ at USE_OSX_ATTR_TRUE@am__append_80 = plugins/osx_attr
+ at MONOLITHIC_TRUE@@USE_OSX_ATTR_TRUE at am__append_81 = plugins/osx_attr/libstrongswan-osx-attr.la
+ at USE_ANDROID_DNS_TRUE@am__append_82 = plugins/android_dns
+ at MONOLITHIC_TRUE@@USE_ANDROID_DNS_TRUE at am__append_83 = plugins/android_dns/libstrongswan-android-dns.la
+ at USE_ANDROID_LOG_TRUE@am__append_84 = plugins/android_log
+ at MONOLITHIC_TRUE@@USE_ANDROID_LOG_TRUE at am__append_85 = plugins/android_log/libstrongswan-android-log.la
+ at USE_MAEMO_TRUE@am__append_86 = plugins/maemo
+ at MONOLITHIC_TRUE@@USE_MAEMO_TRUE at am__append_87 = plugins/maemo/libstrongswan-maemo.la
+ at USE_HA_TRUE@am__append_88 = plugins/ha
+ at MONOLITHIC_TRUE@@USE_HA_TRUE at am__append_89 = plugins/ha/libstrongswan-ha.la
+ at USE_KERNEL_LIBIPSEC_TRUE@am__append_90 = plugins/kernel_libipsec
+ at MONOLITHIC_TRUE@@USE_KERNEL_LIBIPSEC_TRUE at am__append_91 = plugins/kernel_libipsec/libstrongswan-kernel-libipsec.la
+ at USE_KERNEL_WFP_TRUE@am__append_92 = plugins/kernel_wfp
+ at MONOLITHIC_TRUE@@USE_KERNEL_WFP_TRUE at am__append_93 = plugins/kernel_wfp/libstrongswan-kernel-wfp.la
+ at USE_KERNEL_IPH_TRUE@am__append_94 = plugins/kernel_iph
+ at MONOLITHIC_TRUE@@USE_KERNEL_IPH_TRUE at am__append_95 = plugins/kernel_iph/libstrongswan-kernel-iph.la
+ at USE_WHITELIST_TRUE@am__append_96 = plugins/whitelist
+ at MONOLITHIC_TRUE@@USE_WHITELIST_TRUE at am__append_97 = plugins/whitelist/libstrongswan-whitelist.la
+ at USE_LOOKIP_TRUE@am__append_98 = plugins/lookip
+ at MONOLITHIC_TRUE@@USE_LOOKIP_TRUE at am__append_99 = plugins/lookip/libstrongswan-lookip.la
+ at USE_ERROR_NOTIFY_TRUE@am__append_100 = plugins/error_notify
+ at MONOLITHIC_TRUE@@USE_ERROR_NOTIFY_TRUE at am__append_101 = plugins/error_notify/libstrongswan-error-notify.la
+ at USE_CERTEXPIRE_TRUE@am__append_102 = plugins/certexpire
+ at MONOLITHIC_TRUE@@USE_CERTEXPIRE_TRUE at am__append_103 = plugins/certexpire/libstrongswan-certexpire.la
+ at USE_SYSTIME_FIX_TRUE@am__append_104 = plugins/systime_fix
+ at MONOLITHIC_TRUE@@USE_SYSTIME_FIX_TRUE at am__append_105 = plugins/systime_fix/libstrongswan-systime-fix.la
+ at USE_LED_TRUE@am__append_106 = plugins/led
+ at MONOLITHIC_TRUE@@USE_LED_TRUE at am__append_107 = plugins/led/libstrongswan-led.la
+ at USE_DUPLICHECK_TRUE@am__append_108 = plugins/duplicheck
+ at MONOLITHIC_TRUE@@USE_DUPLICHECK_TRUE at am__append_109 = plugins/duplicheck/libstrongswan-duplicheck.la
+ at USE_COUPLING_TRUE@am__append_110 = plugins/coupling
+ at MONOLITHIC_TRUE@@USE_COUPLING_TRUE at am__append_111 = plugins/coupling/libstrongswan-coupling.la
+ at USE_RADATTR_TRUE@am__append_112 = plugins/radattr
+ at MONOLITHIC_TRUE@@USE_RADATTR_TRUE at am__append_113 = plugins/radattr/libstrongswan-radattr.la
+ at USE_UCI_TRUE@am__append_114 = plugins/uci
+ at MONOLITHIC_TRUE@@USE_UCI_TRUE at am__append_115 = plugins/uci/libstrongswan-uci.la
+ at USE_ADDRBLOCK_TRUE@am__append_116 = plugins/addrblock
+ at MONOLITHIC_TRUE@@USE_ADDRBLOCK_TRUE at am__append_117 = plugins/addrblock/libstrongswan-addrblock.la
+ at USE_UNITY_TRUE@am__append_118 = plugins/unity
+ at MONOLITHIC_TRUE@@USE_UNITY_TRUE at am__append_119 = plugins/unity/libstrongswan-unity.la
+ at USE_UNIT_TESTS_TRUE@am__append_120 = plugins/unit_tester
+ at MONOLITHIC_TRUE@@USE_UNIT_TESTS_TRUE at am__append_121 = plugins/unit_tester/libstrongswan-unit-tester.la
+ at USE_XAUTH_GENERIC_TRUE@am__append_122 = plugins/xauth_generic
+ at MONOLITHIC_TRUE@@USE_XAUTH_GENERIC_TRUE at am__append_123 = plugins/xauth_generic/libstrongswan-xauth-generic.la
+ at USE_XAUTH_EAP_TRUE@am__append_124 = plugins/xauth_eap
+ at MONOLITHIC_TRUE@@USE_XAUTH_EAP_TRUE at am__append_125 = plugins/xauth_eap/libstrongswan-xauth-eap.la
+ at USE_XAUTH_PAM_TRUE@am__append_126 = plugins/xauth_pam
+ at MONOLITHIC_TRUE@@USE_XAUTH_PAM_TRUE at am__append_127 = plugins/xauth_pam/libstrongswan-xauth-pam.la
+ at USE_XAUTH_NOAUTH_TRUE@am__append_128 = plugins/xauth_noauth
+ at MONOLITHIC_TRUE@@USE_XAUTH_NOAUTH_TRUE at am__append_129 = plugins/xauth_noauth/libstrongswan-xauth-noauth.la
 subdir = src/libcharon
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -303,31 +315,32 @@ 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__append_5) \
-	$(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_42) $(am__append_44) $(am__append_46) \
-	$(am__append_48) $(am__append_50) $(am__append_52) \
-	$(am__append_54) $(am__append_56) $(am__append_58) \
-	$(am__append_60) $(am__append_61) $(am__append_62) \
+	$(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_48) $(am__append_50) \
+	$(am__append_52) $(am__append_54) $(am__append_56) \
+	$(am__append_58) $(am__append_60) $(am__append_62) \
 	$(am__append_64) $(am__append_66) $(am__append_67) \
-	$(am__append_69) $(am__append_71) $(am__append_73) \
-	$(am__append_75) $(am__append_77) $(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_68) $(am__append_70) $(am__append_72) \
+	$(am__append_73) $(am__append_75) $(am__append_77) \
+	$(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__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
 	bus/listeners/listener.h bus/listeners/logger.h \
 	bus/listeners/file_logger.c bus/listeners/file_logger.h \
-	bus/listeners/sys_logger.c bus/listeners/sys_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 \
@@ -468,6 +481,7 @@ am__libcharon_la_SOURCES_DIST = bus/bus.c bus/bus.h \
 	processing/jobs/dpd_timeout_job.h \
 	processing/jobs/adopt_children_job.c \
 	processing/jobs/adopt_children_job.h \
+	bus/listeners/sys_logger.c bus/listeners/sys_logger.h \
 	encoding/payloads/endpoint_notify.c \
 	encoding/payloads/endpoint_notify.h \
 	processing/jobs/initiate_mediation_job.c \
@@ -519,17 +533,18 @@ am__dirstamp = $(am__leading_dot)dirstamp
 @USE_IKEV1_TRUE@	sa/ikev1/tasks/mode_config.lo \
 @USE_IKEV1_TRUE@	processing/jobs/dpd_timeout_job.lo \
 @USE_IKEV1_TRUE@	processing/jobs/adopt_children_job.lo
- at USE_ME_TRUE@am__objects_3 = encoding/payloads/endpoint_notify.lo \
+ at USE_SYSLOG_TRUE@am__objects_3 = bus/listeners/sys_logger.lo
+ at USE_ME_TRUE@am__objects_4 = encoding/payloads/endpoint_notify.lo \
 @USE_ME_TRUE@	processing/jobs/initiate_mediation_job.lo \
 @USE_ME_TRUE@	processing/jobs/mediation_job.lo \
 @USE_ME_TRUE@	sa/ikev2/connect_manager.lo \
 @USE_ME_TRUE@	sa/ikev2/mediation_manager.lo \
 @USE_ME_TRUE@	sa/ikev2/tasks/ike_me.lo
 am_libcharon_la_OBJECTS = bus/bus.lo bus/listeners/file_logger.lo \
-	bus/listeners/sys_logger.lo config/backend_manager.lo \
-	config/child_cfg.lo config/ike_cfg.lo config/peer_cfg.lo \
-	config/proposal.lo control/controller.lo daemon.lo \
-	encoding/generator.lo encoding/message.lo encoding/parser.lo \
+	config/backend_manager.lo config/child_cfg.lo \
+	config/ike_cfg.lo config/peer_cfg.lo config/proposal.lo \
+	control/controller.lo daemon.lo encoding/generator.lo \
+	encoding/message.lo encoding/parser.lo \
 	encoding/payloads/auth_payload.lo \
 	encoding/payloads/cert_payload.lo \
 	encoding/payloads/certreq_payload.lo \
@@ -574,7 +589,8 @@ am_libcharon_la_OBJECTS = bus/bus.lo bus/listeners/file_logger.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/task_manager.lo sa/shunt_manager.lo sa/trap_manager.lo \
-	sa/task.lo $(am__objects_1) $(am__objects_2) $(am__objects_3)
+	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@)
@@ -657,8 +673,9 @@ am__define_uniq_tagged_files = \
 ETAGS = etags
 CTAGS = ctags
 DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \
-	plugins/socket_dynamic plugins/farp plugins/stroke plugins/smp \
-	plugins/sql plugins/dnscert plugins/ipseckey plugins/updown \
+	plugins/socket_dynamic plugins/socket_win plugins/farp \
+	plugins/stroke plugins/vici plugins/smp plugins/sql \
+	plugins/dnscert plugins/ipseckey plugins/updown \
 	plugins/eap_identity plugins/eap_sim plugins/eap_sim_file \
 	plugins/eap_sim_pcsc plugins/eap_simaka_sql \
 	plugins/eap_simaka_pseudonym plugins/eap_simaka_reauth \
@@ -669,12 +686,12 @@ DIST_SUBDIRS = . plugins/load_tester plugins/socket_default \
 	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/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/unit_tester plugins/xauth_generic plugins/xauth_eap \
-	plugins/xauth_pam plugins/xauth_noauth
+	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/unit_tester plugins/xauth_generic \
+	plugins/xauth_eap plugins/xauth_pam plugins/xauth_noauth
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 am__relativize = \
   dir0=`pwd`; \
@@ -763,6 +780,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -781,6 +799,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -808,6 +827,7 @@ 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@
@@ -899,6 +919,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -912,8 +933,7 @@ xml_LIBS = @xml_LIBS@
 ipseclib_LTLIBRARIES = libcharon.la
 libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
 	bus/listeners/logger.h bus/listeners/file_logger.c \
-	bus/listeners/file_logger.h bus/listeners/sys_logger.c \
-	bus/listeners/sys_logger.h config/backend_manager.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 \
@@ -1001,7 +1021,7 @@ libcharon_la_SOURCES = bus/bus.c bus/bus.h bus/listeners/listener.h \
 	sa/ike_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) \
-	$(am__append_2) $(am__append_3)
+	$(am__append_2) $(am__append_3) $(am__append_5)
 AM_CPPFLAGS = \
 	-I${linux_headers} \
 	-I$(top_srcdir)/src/libstrongswan \
@@ -1016,19 +1036,19 @@ AM_LDFLAGS = \
 libcharon_la_LIBADD =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libhydra/libhydra.la -lm $(PTHREADLIB) \
-	$(DLLIB) $(SOCKLIB) $(am__append_5) $(am__append_7) \
+	$(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_42) \
-	$(am__append_44) $(am__append_46) $(am__append_48) \
+	$(am__append_39) $(am__append_41) $(am__append_43) \
+	$(am__append_45) $(am__append_47) $(am__append_48) \
 	$(am__append_50) $(am__append_52) $(am__append_54) \
 	$(am__append_56) $(am__append_58) $(am__append_60) \
-	$(am__append_61) $(am__append_62) $(am__append_64) \
-	$(am__append_66) $(am__append_67) $(am__append_69) \
-	$(am__append_71) $(am__append_73) $(am__append_75) \
+	$(am__append_62) $(am__append_64) $(am__append_66) \
+	$(am__append_67) $(am__append_68) $(am__append_70) \
+	$(am__append_72) $(am__append_73) $(am__append_75) \
 	$(am__append_77) $(am__append_79) $(am__append_81) \
 	$(am__append_83) $(am__append_85) $(am__append_87) \
 	$(am__append_89) $(am__append_91) $(am__append_93) \
@@ -1036,67 +1056,72 @@ libcharon_la_LIBADD =  \
 	$(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_119) $(am__append_121) $(am__append_123) \
+	$(am__append_125) $(am__append_127) $(am__append_129)
 EXTRA_DIST = Android.mk
- at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_4) $(am__append_6) \
- at MONOLITHIC_FALSE@	$(am__append_8) $(am__append_10) \
- at MONOLITHIC_FALSE@	$(am__append_12) $(am__append_14) \
- at MONOLITHIC_FALSE@	$(am__append_16) $(am__append_18) \
- at MONOLITHIC_FALSE@	$(am__append_20) $(am__append_22) \
- at MONOLITHIC_FALSE@	$(am__append_24) $(am__append_26) \
- at MONOLITHIC_FALSE@	$(am__append_28) $(am__append_30) \
- at MONOLITHIC_FALSE@	$(am__append_32) $(am__append_34) \
- at MONOLITHIC_FALSE@	$(am__append_36) $(am__append_38) \
- at MONOLITHIC_FALSE@	$(am__append_40) $(am__append_43) \
- at MONOLITHIC_FALSE@	$(am__append_45) $(am__append_47) \
- at MONOLITHIC_FALSE@	$(am__append_49) $(am__append_51) \
- at MONOLITHIC_FALSE@	$(am__append_53) $(am__append_55) \
- at MONOLITHIC_FALSE@	$(am__append_57) $(am__append_59) \
+ at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_6) $(am__append_8) \
+ at MONOLITHIC_FALSE@	$(am__append_10) $(am__append_12) \
+ at MONOLITHIC_FALSE@	$(am__append_14) $(am__append_16) \
+ at MONOLITHIC_FALSE@	$(am__append_18) $(am__append_20) \
+ at MONOLITHIC_FALSE@	$(am__append_22) $(am__append_24) \
+ at MONOLITHIC_FALSE@	$(am__append_26) $(am__append_28) \
+ at MONOLITHIC_FALSE@	$(am__append_30) $(am__append_32) \
+ at MONOLITHIC_FALSE@	$(am__append_34) $(am__append_36) \
+ at MONOLITHIC_FALSE@	$(am__append_38) $(am__append_40) \
+ at MONOLITHIC_FALSE@	$(am__append_42) $(am__append_44) \
+ at MONOLITHIC_FALSE@	$(am__append_46) $(am__append_49) \
+ at MONOLITHIC_FALSE@	$(am__append_51) $(am__append_53) \
+ at MONOLITHIC_FALSE@	$(am__append_55) $(am__append_57) \
+ at MONOLITHIC_FALSE@	$(am__append_59) $(am__append_61) \
 @MONOLITHIC_FALSE@	$(am__append_63) $(am__append_65) \
- at MONOLITHIC_FALSE@	$(am__append_68) $(am__append_70) \
- at MONOLITHIC_FALSE@	$(am__append_72) $(am__append_74) \
- at MONOLITHIC_FALSE@	$(am__append_76) $(am__append_78) \
- at MONOLITHIC_FALSE@	$(am__append_80) $(am__append_82) \
- at MONOLITHIC_FALSE@	$(am__append_84) $(am__append_86) \
- at MONOLITHIC_FALSE@	$(am__append_88) $(am__append_90) \
- at MONOLITHIC_FALSE@	$(am__append_92) $(am__append_94) \
- at MONOLITHIC_FALSE@	$(am__append_96) $(am__append_98) \
- at MONOLITHIC_FALSE@	$(am__append_100) $(am__append_102) \
- at MONOLITHIC_FALSE@	$(am__append_104) $(am__append_106) \
- at MONOLITHIC_FALSE@	$(am__append_108) $(am__append_110) \
- at MONOLITHIC_FALSE@	$(am__append_112) $(am__append_114) \
- at MONOLITHIC_FALSE@	$(am__append_116) $(am__append_118)
+ at MONOLITHIC_FALSE@	$(am__append_69) $(am__append_71) \
+ at MONOLITHIC_FALSE@	$(am__append_74) $(am__append_76) \
+ at MONOLITHIC_FALSE@	$(am__append_78) $(am__append_80) \
+ at MONOLITHIC_FALSE@	$(am__append_82) $(am__append_84) \
+ at MONOLITHIC_FALSE@	$(am__append_86) $(am__append_88) \
+ at MONOLITHIC_FALSE@	$(am__append_90) $(am__append_92) \
+ at MONOLITHIC_FALSE@	$(am__append_94) $(am__append_96) \
+ at MONOLITHIC_FALSE@	$(am__append_98) $(am__append_100) \
+ at MONOLITHIC_FALSE@	$(am__append_102) $(am__append_104) \
+ at MONOLITHIC_FALSE@	$(am__append_106) $(am__append_108) \
+ at MONOLITHIC_FALSE@	$(am__append_110) $(am__append_112) \
+ at MONOLITHIC_FALSE@	$(am__append_114) $(am__append_116) \
+ at MONOLITHIC_FALSE@	$(am__append_118) $(am__append_120) \
+ at MONOLITHIC_FALSE@	$(am__append_122) $(am__append_124) \
+ at MONOLITHIC_FALSE@	$(am__append_126) $(am__append_128)
 
 # build optional plugins
 ########################
- at MONOLITHIC_TRUE@SUBDIRS = $(am__append_4) $(am__append_6) \
- at MONOLITHIC_TRUE@	$(am__append_8) $(am__append_10) \
- at MONOLITHIC_TRUE@	$(am__append_12) $(am__append_14) \
- at MONOLITHIC_TRUE@	$(am__append_16) $(am__append_18) \
- at MONOLITHIC_TRUE@	$(am__append_20) $(am__append_22) \
- at MONOLITHIC_TRUE@	$(am__append_24) $(am__append_26) \
- at MONOLITHIC_TRUE@	$(am__append_28) $(am__append_30) \
- at MONOLITHIC_TRUE@	$(am__append_32) $(am__append_34) \
- at MONOLITHIC_TRUE@	$(am__append_36) $(am__append_38) \
- at MONOLITHIC_TRUE@	$(am__append_40) $(am__append_43) \
- at MONOLITHIC_TRUE@	$(am__append_45) $(am__append_47) \
- at MONOLITHIC_TRUE@	$(am__append_49) $(am__append_51) \
- at MONOLITHIC_TRUE@	$(am__append_53) $(am__append_55) \
- at MONOLITHIC_TRUE@	$(am__append_57) $(am__append_59) \
+ at MONOLITHIC_TRUE@SUBDIRS = $(am__append_6) $(am__append_8) \
+ at MONOLITHIC_TRUE@	$(am__append_10) $(am__append_12) \
+ at MONOLITHIC_TRUE@	$(am__append_14) $(am__append_16) \
+ at MONOLITHIC_TRUE@	$(am__append_18) $(am__append_20) \
+ at MONOLITHIC_TRUE@	$(am__append_22) $(am__append_24) \
+ at MONOLITHIC_TRUE@	$(am__append_26) $(am__append_28) \
+ at MONOLITHIC_TRUE@	$(am__append_30) $(am__append_32) \
+ at MONOLITHIC_TRUE@	$(am__append_34) $(am__append_36) \
+ at MONOLITHIC_TRUE@	$(am__append_38) $(am__append_40) \
+ at MONOLITHIC_TRUE@	$(am__append_42) $(am__append_44) \
+ at MONOLITHIC_TRUE@	$(am__append_46) $(am__append_49) \
+ at MONOLITHIC_TRUE@	$(am__append_51) $(am__append_53) \
+ at MONOLITHIC_TRUE@	$(am__append_55) $(am__append_57) \
+ at MONOLITHIC_TRUE@	$(am__append_59) $(am__append_61) \
 @MONOLITHIC_TRUE@	$(am__append_63) $(am__append_65) \
- at MONOLITHIC_TRUE@	$(am__append_68) $(am__append_70) \
- at MONOLITHIC_TRUE@	$(am__append_72) $(am__append_74) \
- at MONOLITHIC_TRUE@	$(am__append_76) $(am__append_78) \
- at MONOLITHIC_TRUE@	$(am__append_80) $(am__append_82) \
- at MONOLITHIC_TRUE@	$(am__append_84) $(am__append_86) \
- at MONOLITHIC_TRUE@	$(am__append_88) $(am__append_90) \
- at MONOLITHIC_TRUE@	$(am__append_92) $(am__append_94) \
- at MONOLITHIC_TRUE@	$(am__append_96) $(am__append_98) \
- at MONOLITHIC_TRUE@	$(am__append_100) $(am__append_102) \
- at MONOLITHIC_TRUE@	$(am__append_104) $(am__append_106) \
- at MONOLITHIC_TRUE@	$(am__append_108) $(am__append_110) \
- at MONOLITHIC_TRUE@	$(am__append_112) $(am__append_114) \
- at MONOLITHIC_TRUE@	$(am__append_116) $(am__append_118)
+ at MONOLITHIC_TRUE@	$(am__append_69) $(am__append_71) \
+ at MONOLITHIC_TRUE@	$(am__append_74) $(am__append_76) \
+ at MONOLITHIC_TRUE@	$(am__append_78) $(am__append_80) \
+ at MONOLITHIC_TRUE@	$(am__append_82) $(am__append_84) \
+ at MONOLITHIC_TRUE@	$(am__append_86) $(am__append_88) \
+ at MONOLITHIC_TRUE@	$(am__append_90) $(am__append_92) \
+ at MONOLITHIC_TRUE@	$(am__append_94) $(am__append_96) \
+ at MONOLITHIC_TRUE@	$(am__append_98) $(am__append_100) \
+ at MONOLITHIC_TRUE@	$(am__append_102) $(am__append_104) \
+ at MONOLITHIC_TRUE@	$(am__append_106) $(am__append_108) \
+ at MONOLITHIC_TRUE@	$(am__append_110) $(am__append_112) \
+ at MONOLITHIC_TRUE@	$(am__append_114) $(am__append_116) \
+ at MONOLITHIC_TRUE@	$(am__append_118) $(am__append_120) \
+ at MONOLITHIC_TRUE@	$(am__append_122) $(am__append_124) \
+ at MONOLITHIC_TRUE@	$(am__append_126) $(am__append_128)
 all: all-recursive
 
 .SUFFIXES:
@@ -1181,8 +1206,6 @@ bus/listeners/$(DEPDIR)/$(am__dirstamp):
 	@: > bus/listeners/$(DEPDIR)/$(am__dirstamp)
 bus/listeners/file_logger.lo: bus/listeners/$(am__dirstamp) \
 	bus/listeners/$(DEPDIR)/$(am__dirstamp)
-bus/listeners/sys_logger.lo: bus/listeners/$(am__dirstamp) \
-	bus/listeners/$(DEPDIR)/$(am__dirstamp)
 config/$(am__dirstamp):
 	@$(MKDIR_P) config
 	@: > config/$(am__dirstamp)
@@ -1513,6 +1536,8 @@ processing/jobs/dpd_timeout_job.lo: processing/jobs/$(am__dirstamp) \
 processing/jobs/adopt_children_job.lo:  \
 	processing/jobs/$(am__dirstamp) \
 	processing/jobs/$(DEPDIR)/$(am__dirstamp)
+bus/listeners/sys_logger.lo: bus/listeners/$(am__dirstamp) \
+	bus/listeners/$(DEPDIR)/$(am__dirstamp)
 encoding/payloads/endpoint_notify.lo:  \
 	encoding/payloads/$(am__dirstamp) \
 	encoding/payloads/$(DEPDIR)/$(am__dirstamp)
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index b461848..d1c138c 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Tobias Brunner
+ * Copyright (C) 2011-2014 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -23,6 +23,31 @@
 #include <threading/mutex.h>
 #include <threading/rwlock.h>
 
+/**
+ * These operations allow us to speed up the log level checks on some platforms.
+ * In particular if acquiring the read lock is expensive even in the absence of
+ * any writers.
+ *
+ * Note that while holding the read/write lock the read does not have to be
+ * atomic as the write lock must be held to set the level.
+ */
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+
+#define skip_level(ptr, level) (__atomic_load_n(ptr, __ATOMIC_RELAXED) < level)
+#define set_level(ptr, val) __atomic_store_n(ptr, val, __ATOMIC_RELAXED)
+
+#elif defined(HAVE_GCC_SYNC_OPERATIONS)
+
+#define skip_level(ptr, level) (__sync_fetch_and_add(ptr, 0) < level)
+#define set_level(ptr, val) __sync_bool_compare_and_swap(ptr, *ptr, val)
+
+#else
+
+#define skip_level(ptr, level) FALSE
+#define set_level(ptr, val) ({ *ptr = val; })
+
+#endif
+
 typedef struct private_bus_t private_bus_t;
 
 /**
@@ -173,11 +198,12 @@ static inline void register_logger(private_bus_t *this, debug_t group,
 
 	if (entry->logger->log)
 	{
-		this->max_level[group] = max(this->max_level[group], level);
+		set_level(&this->max_level[group], max(this->max_level[group], level));
 	}
 	if (entry->logger->vlog)
 	{
-		this->max_vlevel[group] = max(this->max_vlevel[group], level);
+		set_level(&this->max_vlevel[group],
+				  max(this->max_vlevel[group], level));
 	}
 }
 
@@ -205,6 +231,7 @@ static inline void unregister_logger(private_bus_t *this, logger_t *logger)
 
 	if (found)
 	{
+		level_t level = LEVEL_SILENT, vlevel = LEVEL_SILENT;
 		debug_t group;
 
 		for (group = 0; group < DBG_MAX; group++)
@@ -214,13 +241,19 @@ static inline void unregister_logger(private_bus_t *this, logger_t *logger)
 				loggers = this->loggers[group];
 				loggers->remove(loggers, found, NULL);
 
-				this->max_level[group] = LEVEL_SILENT;
-				this->max_vlevel[group] = LEVEL_SILENT;
 				if (loggers->get_first(loggers, (void**)&entry) == SUCCESS)
 				{
-					this->max_level[group] = entry->levels[group];
-					this->max_vlevel[group] = entry->levels[group];
+					if (entry->logger->log)
+					{
+						level = entry->levels[group];
+					}
+					if (entry->logger->vlog)
+					{
+						vlevel = entry->levels[group];
+					}
 				}
+				set_level(&this->max_level[group], level);
+				set_level(&this->max_vlevel[group], vlevel);
 			}
 		}
 		free(found);
@@ -324,6 +357,19 @@ METHOD(bus_t, vlog, void,
 	linked_list_t *loggers;
 	log_data_t data;
 
+	/* NOTE: This is not 100% thread-safe and done here only because it is
+	 * performance critical.  We therefore ignore the following two issues for
+	 * this particular case:  1) We might miss some log messages if another
+	 * thread concurrently increases the log level or registers a new logger.
+	 * 2) We might have to acquire the read lock below even if it wouldn't be
+	 * necessary anymore due to another thread concurrently unregistering a
+	 * logger or reducing the level. */
+	if (skip_level(&this->max_level[group], level) &&
+		skip_level(&this->max_vlevel[group], level))
+	{
+		return;
+	}
+
 	this->log_lock->read_lock(this->log_lock);
 	loggers = this->loggers[group];
 
@@ -345,7 +391,9 @@ METHOD(bus_t, vlog, void,
 		{
 			len++;
 			data.message = malloc(len);
-			len = vsnprintf(data.message, len, format, args);
+			va_copy(data.args, args);
+			len = vsnprintf(data.message, len, format, data.args);
+			va_end(data.args);
 		}
 		if (len > 0)
 		{
@@ -833,6 +881,33 @@ METHOD(bus_t, assign_vips, void,
 	this->mutex->unlock(this->mutex);
 }
 
+METHOD(bus_t, handle_vips, void,
+	private_bus_t *this, ike_sa_t *ike_sa, bool handle)
+{
+	enumerator_t *enumerator;
+	entry_t *entry;
+	bool keep;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->listeners->create_enumerator(this->listeners);
+	while (enumerator->enumerate(enumerator, &entry))
+	{
+		if (entry->calling || !entry->listener->handle_vips)
+		{
+			continue;
+		}
+		entry->calling++;
+		keep = entry->listener->handle_vips(entry->listener, ike_sa, handle);
+		entry->calling--;
+		if (!keep)
+		{
+			unregister_listener(this, entry, enumerator);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
 /**
  * Credential manager hook function to forward bus alerts
  */
@@ -909,6 +984,7 @@ bus_t *bus_create()
 			.authorize = _authorize,
 			.narrow = _narrow,
 			.assign_vips = _assign_vips,
+			.handle_vips = _handle_vips,
 			.destroy = _destroy,
 		},
 		.listeners = linked_list_create(),
diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h
index 4a0ac68..1d708c5 100644
--- a/src/libcharon/bus/bus.h
+++ b/src/libcharon/bus/bus.h
@@ -412,6 +412,14 @@ struct bus_t {
 	void (*assign_vips)(bus_t *this, ike_sa_t *ike_sa, bool assign);
 
 	/**
+	 * Virtual IP handler hook.
+	 *
+	 * @param ike_sa	IKE_SA the VIPs/attributes got handled on
+	 * @param assign	TRUE after installing attributes, FALSE on release
+	 */
+	void (*handle_vips)(bus_t *this, ike_sa_t *ike_sa, bool handle);
+
+	/**
 	 * Destroy the event bus.
 	 */
 	void (*destroy) (bus_t *this);
diff --git a/src/libcharon/bus/listeners/file_logger.c b/src/libcharon/bus/listeners/file_logger.c
index 68a386d..e3661bd 100644
--- a/src/libcharon/bus/listeners/file_logger.c
+++ b/src/libcharon/bus/listeners/file_logger.c
@@ -50,6 +50,11 @@ struct private_file_logger_t {
 	FILE *out;
 
 	/**
+	 * Flush after writing a line?
+	 */
+	bool flush_line;
+
+	/**
 	 * Maximum level to log, for each group
 	 */
 	level_t levels[DBG_MAX];
@@ -137,6 +142,12 @@ METHOD(logger_t, log_, void,
 		fprintf(this->out, "%.*s\n", (int)(next - current), current);
 		current = next + 1;
 	}
+#ifndef HAVE_SETLINEBUF
+	if (this->flush_line)
+	{
+		fflush(this->out);
+	}
+#endif /* !HAVE_SETLINEBUF */
 	this->mutex->unlock(this->mutex);
 	this->lock->unlock(this->lock);
 }
@@ -214,14 +225,17 @@ METHOD(file_logger_t, open_, void,
 				 this->filename, strerror(errno));
 			return;
 		}
+#ifdef HAVE_SETLINEBUF
 		if (flush_line)
 		{
 			setlinebuf(file);
 		}
+#endif /* HAVE_SETLINEBUF */
 	}
 	this->lock->write_lock(this->lock);
 	close_file(this);
 	this->out = file;
+	this->flush_line = flush_line;
 	this->lock->unlock(this->lock);
 }
 
diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h
index 57445df..abcc765 100644
--- a/src/libcharon/bus/listeners/listener.h
+++ b/src/libcharon/bus/listeners/listener.h
@@ -192,10 +192,10 @@ struct listener_t {
 				narrow_hook_t type, linked_list_t *local, linked_list_t *remote);
 
 	/**
-	 * Virtual IP address assignment hook
+	 * Virtual IP address assignment hook.
 	 *
-	 * This hook gets invoked when a a Virtual IP address is assigned to an
-	 * IKE_SA (assign = TRUE) and again when it is released (assign = FALSE)
+	 * This hook gets invoked after virtual IPs have been assigned to a peer
+	 * for a specific IKE_SA, and again before they get released.
 	 *
 	 * @param ike_sa	IKE_SA the VIPs are assigned to
 	 * @param assign	TRUE if assigned to IKE_SA, FALSE if released
@@ -203,6 +203,18 @@ struct listener_t {
 	 */
 	bool (*assign_vips)(listener_t *this, ike_sa_t *ike_sa, bool assign);
 
+	/**
+	 * Virtual IP and configuration attribute handler hook.
+	 *
+	 * This hook gets invoked after virtual IP and other configuration
+	 * attributes just got installed or are about to get uninstalled on a peer
+	 * receiving them.
+	 *
+	 * @param ike_sa	IKE_SA the VIPs/attributes are handled on
+	 * @param handle	TRUE if handled by IKE_SA, FALSE on release
+	 * @return			TRUE to stay registered, FALSE to unregister
+	 */
+	bool (*handle_vips)(listener_t *this, ike_sa_t *ike_sa, bool handle);
 };
 
 #endif /** LISTENER_H_ @}*/
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index 6fe7d44..7e4a143 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -27,6 +27,9 @@ ENUM(action_names, ACTION_NONE, ACTION_RESTART,
 	"restart",
 );
 
+/** Default replay window size, if not set using charon.replay_window */
+#define DEFAULT_REPLAY_WINDOW 32
+
 typedef struct private_child_cfg_t private_child_cfg_t;
 
 /**
@@ -138,6 +141,11 @@ struct private_child_cfg_t {
 	 * enable installation and removal of kernel IPsec policies
 	 */
 	bool install_policy;
+
+	/**
+	 * anti-replay window size
+	 */
+	u_int32_t replay_window;
 };
 
 METHOD(child_cfg_t, get_name, char*,
@@ -149,7 +157,10 @@ METHOD(child_cfg_t, get_name, char*,
 METHOD(child_cfg_t, add_proposal, void,
 	private_child_cfg_t *this, proposal_t *proposal)
 {
-	this->proposals->insert_last(this->proposals, proposal);
+	if (proposal)
+	{
+		this->proposals->insert_last(this->proposals, proposal);
+	}
 }
 
 METHOD(child_cfg_t, get_proposals, linked_list_t*,
@@ -354,11 +365,11 @@ METHOD(child_cfg_t, get_traffic_selectors, linked_list_t*,
 				{
 					result->remove_at(result, e1);
 					ts1->destroy(ts1);
-					result->reset_enumerator(result, e2);
 					break;
 				}
 			}
 		}
+		result->reset_enumerator(result, e2);
 	}
 	e1->destroy(e1);
 	e2->destroy(e2);
@@ -478,6 +489,18 @@ METHOD(child_cfg_t, get_tfc, u_int32_t,
 	return this->tfc;
 }
 
+METHOD(child_cfg_t, get_replay_window, u_int32_t,
+	private_child_cfg_t *this)
+{
+	return this->replay_window;
+}
+
+METHOD(child_cfg_t, set_replay_window, void,
+	private_child_cfg_t *this, u_int32_t replay_window)
+{
+	this->replay_window = replay_window;
+}
+
 METHOD(child_cfg_t, set_mipv6_options, void,
 	private_child_cfg_t *this, bool proxy_mode, bool install_policy)
 {
@@ -555,6 +578,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
 			.get_reqid = _get_reqid,
 			.get_mark = _get_mark,
 			.get_tfc = _get_tfc,
+			.get_replay_window = _get_replay_window,
+			.set_replay_window = _set_replay_window,
 			.use_proxy_mode = _use_proxy_mode,
 			.install_policy = _install_policy,
 			.get_ref = _get_ref,
@@ -577,6 +602,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
 		.my_ts = linked_list_create(),
 		.other_ts = linked_list_create(),
 		.tfc = tfc,
+		.replay_window = lib->settings->get_int(lib->settings,
+				"%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
 	);
 
 	if (mark_in)
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index 20d1fa8..9f7a92b 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -73,10 +73,10 @@ struct child_cfg_t {
 	 * Add a proposal to the list.
 	 *
 	 * The proposals are stored by priority, first added
-	 * is the most preferred.
-	 * After add, proposal is owned by child_cfg.
+	 * is the most preferred. It is safe to add NULL as proposal, which has no
+	 * effect. After add, proposal is owned by child_cfg.
 	 *
-	 * @param proposal		proposal to add
+	 * @param proposal		proposal to add, or NULL
 	 */
 	void (*add_proposal) (child_cfg_t *this, proposal_t *proposal);
 
@@ -235,6 +235,20 @@ struct child_cfg_t {
 	u_int32_t (*get_tfc)(child_cfg_t *this);
 
 	/**
+	 * Get anti-replay window size
+	 *
+	 * @return				anti-replay window size
+	 */
+	u_int32_t (*get_replay_window)(child_cfg_t *this);
+
+	/**
+	 * Set anti-replay window size
+	 *
+	 * @param window		anti-replay window size
+	 */
+	void (*set_replay_window)(child_cfg_t *this, u_int32_t window);
+
+	/**
 	 * Sets two options needed for Mobile IPv6 interoperability.
 	 *
 	 * @param proxy_mode	use IPsec transport proxy mode (default FALSE)
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index e08bb3f..42a3e90 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -281,7 +281,10 @@ METHOD(ike_cfg_t, get_dscp, u_int8_t,
 METHOD(ike_cfg_t, add_proposal, void,
 	private_ike_cfg_t *this, proposal_t *proposal)
 {
-	this->proposals->insert_last(this->proposals, proposal);
+	if (proposal)
+	{
+		this->proposals->insert_last(this->proposals, proposal);
+	}
 }
 
 METHOD(ike_cfg_t, get_proposals, linked_list_t*,
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
index f9e4fbe..adfcabf 100644
--- a/src/libcharon/config/ike_cfg.h
+++ b/src/libcharon/config/ike_cfg.h
@@ -148,9 +148,10 @@ struct ike_cfg_t {
 	 * Adds a proposal to the list.
 	 *
 	 * The first added proposal has the highest priority, the last
-	 * added the lowest.
+	 * added the lowest. It is safe to add NULL as proposal, which has no
+	 * effect.
 	 *
-	 * @param proposal		proposal to add
+	 * @param proposal		proposal to add, or NULL
 	 */
 	void (*add_proposal) (ike_cfg_t *this, proposal_t *proposal);
 
diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c
index d198503..ce93010 100644
--- a/src/libcharon/config/peer_cfg.c
+++ b/src/libcharon/config/peer_cfg.c
@@ -31,7 +31,8 @@ ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
 	"CERT_NEVER_SEND",
 );
 
-ENUM(unique_policy_names, UNIQUE_NO, UNIQUE_KEEP,
+ENUM(unique_policy_names, UNIQUE_NEVER, UNIQUE_KEEP,
+	"UNIQUE_NEVER",
 	"UNIQUE_NO",
 	"UNIQUE_REPLACE",
 	"UNIQUE_KEEP",
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index 2ecdb4f..4d881cd 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -627,7 +627,7 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number)
 /**
  * Add supported IKE algorithms to proposal
  */
-static void proposal_add_supported_ike(private_proposal_t *this)
+static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
 {
 	enumerator_t *enumerator;
 	encryption_algorithm_t encryption;
@@ -636,76 +636,91 @@ static void proposal_add_supported_ike(private_proposal_t *this)
 	diffie_hellman_group_t group;
 	const char *plugin_name;
 
-	enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
-	while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
+	if (aead)
 	{
-		switch (encryption)
+		enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
+		while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
 		{
-			case ENCR_AES_CBC:
-			case ENCR_AES_CTR:
-			case ENCR_CAMELLIA_CBC:
-			case ENCR_CAMELLIA_CTR:
-				/* 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_3DES:
-				add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
-				break;
-			case ENCR_DES:
-				/* no, thanks */
-				break;
-			default:
-				break;
+			switch (encryption)
+			{
+				case ENCR_AES_CCM_ICV8:
+				case ENCR_AES_CCM_ICV12:
+				case ENCR_AES_CCM_ICV16:
+				case ENCR_AES_GCM_ICV8:
+				case ENCR_AES_GCM_ICV12:
+				case ENCR_AES_GCM_ICV16:
+				case ENCR_CAMELLIA_CCM_ICV8:
+				case ENCR_CAMELLIA_CCM_ICV12:
+				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;
+				default:
+					break;
+			}
 		}
-	}
-	enumerator->destroy(enumerator);
+		enumerator->destroy(enumerator);
 
-	enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
-	while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
-	{
-		switch (encryption)
+		if (!array_count(this->transforms))
 		{
-			case ENCR_AES_CCM_ICV8:
-			case ENCR_AES_CCM_ICV12:
-			case ENCR_AES_CCM_ICV16:
-			case ENCR_AES_GCM_ICV8:
-			case ENCR_AES_GCM_ICV12:
-			case ENCR_AES_GCM_ICV16:
-			case ENCR_CAMELLIA_CCM_ICV8:
-			case ENCR_CAMELLIA_CCM_ICV12:
-			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;
-			default:
-				break;
+			return FALSE;
 		}
 	}
-	enumerator->destroy(enumerator);
-
-	enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
-	while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
+	else
 	{
-		switch (integrity)
+		enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
+		while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
 		{
-			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:
-			case AUTH_AES_XCBC_96:
-			case AUTH_AES_CMAC_96:
-				add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
-				break;
-			default:
-				break;
+			switch (encryption)
+			{
+				case ENCR_AES_CBC:
+				case ENCR_AES_CTR:
+				case ENCR_CAMELLIA_CBC:
+				case ENCR_CAMELLIA_CTR:
+					/* 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_3DES:
+					add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
+					break;
+				case ENCR_DES:
+					/* no, thanks */
+					break;
+				default:
+					break;
+			}
 		}
+		enumerator->destroy(enumerator);
+
+		if (!array_count(this->transforms))
+		{
+			return FALSE;
+		}
+
+		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:
+				case AUTH_AES_XCBC_96:
+				case AUTH_AES_CMAC_96:
+					add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
+					break;
+				default:
+					break;
+			}
+		}
+		enumerator->destroy(enumerator);
 	}
-	enumerator->destroy(enumerator);
 
 	enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
 	while (enumerator->enumerate(enumerator, &prf, &plugin_name))
@@ -767,6 +782,8 @@ static void proposal_add_supported_ike(private_proposal_t *this)
 		}
 	}
 	enumerator->destroy(enumerator);
+
+	return TRUE;
 }
 
 /*
@@ -779,7 +796,11 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
 	switch (protocol)
 	{
 		case PROTO_IKE:
-			proposal_add_supported_ike(this);
+			if (!proposal_add_supported_ike(this, FALSE))
+			{
+				destroy(this);
+				return NULL;
+			}
 			break;
 		case PROTO_ESP:
 			add_algorithm(this, ENCRYPTION_ALGORITHM,   ENCR_AES_CBC,         128);
@@ -807,6 +828,33 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
 /*
  * Describtion in header-file
  */
+proposal_t *proposal_create_default_aead(protocol_id_t protocol)
+{
+	private_proposal_t *this;
+
+	switch (protocol)
+	{
+		case PROTO_IKE:
+			this = (private_proposal_t*)proposal_create(protocol, 0);
+			if (!proposal_add_supported_ike(this, TRUE))
+			{
+				destroy(this);
+				return NULL;
+			}
+			return &this->public;
+		case PROTO_ESP:
+			/* we currently don't include any AEAD proposal for ESP, as we
+			 * don't know if our kernel backend actually supports it. */
+			return NULL;
+		case PROTO_AH:
+		default:
+			return NULL;
+	}
+}
+
+/*
+ * Describtion in header-file
+ */
 proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
 {
 	private_proposal_t *this;
diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h
index 7733143..78b8688 100644
--- a/src/libcharon/config/proposal.h
+++ b/src/libcharon/config/proposal.h
@@ -196,6 +196,14 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number);
 proposal_t *proposal_create_default(protocol_id_t protocol);
 
 /**
+ * Create a default proposal for supported AEAD algorithms
+ *
+ * @param protocol			protocol, such as PROTO_ESP
+ * @return					proposal_t object, NULL if none supported
+ */
+proposal_t *proposal_create_default_aead(protocol_id_t protocol);
+
+/**
  * Create a proposal from a string identifying the algorithms.
  *
  * The string is in the same form as a in the ipsec.conf file.
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
index c546da5..25667e5 100644
--- a/src/libcharon/control/controller.c
+++ b/src/libcharon/control/controller.c
@@ -20,7 +20,6 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <sys/stat.h>
-#include <dlfcn.h>
 
 #include <daemon.h>
 #include <library.h>
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index 0cecd1d..a89995a 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -19,8 +19,12 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <syslog.h>
 #include <time.h>
+#include <errno.h>
+
+#ifdef HAVE_SYSLOG
+#include <syslog.h>
+#endif
 
 #include "daemon.h"
 
@@ -178,6 +182,7 @@ static bool logger_entry_match(logger_entry_t *this, char *target, bool *file)
  */
 static void handle_syslog_identifier(private_daemon_t *this)
 {
+#ifdef HAVE_SYSLOG
 	char *identifier;
 
 	identifier = lib->settings->get_str(lib->settings, "%s.syslog.identifier",
@@ -197,6 +202,7 @@ static void handle_syslog_identifier(private_daemon_t *this)
 		closelog();
 		this->syslog_identifier = NULL;
 	}
+#endif /* HAVE_SYSLOG */
 }
 
 /**
@@ -205,6 +211,7 @@ static void handle_syslog_identifier(private_daemon_t *this)
  */
 static int get_syslog_facility(char *facility)
 {
+#ifdef HAVE_SYSLOG
 	if (streq(facility, "daemon"))
 	{
 		return LOG_DAEMON;
@@ -213,6 +220,7 @@ static int get_syslog_facility(char *facility)
 	{
 		return LOG_AUTHPRIV;
 	}
+#endif /* HAVE_SYSLOG */
 	return -1;
 }
 
@@ -236,10 +244,12 @@ static logger_entry_t *get_logger_entry(char *target, bool is_file_logger,
 		{
 			entry->logger.file = file_logger_create(target);
 		}
+#ifdef HAVE_SYSLOG
 		else
 		{
 			entry->logger.sys = sys_logger_create(get_syslog_facility(target));
 		}
+#endif /* HAVE_SYSLOG */
 	}
 	else
 	{
@@ -380,18 +390,27 @@ METHOD(daemon_t, load_loggers, void,
 
 		for (group = 0; group < DBG_MAX; group++)
 		{
-			sys_logger->set_level(sys_logger, group, levels[group]);
+			if (sys_logger)
+			{
+				sys_logger->set_level(sys_logger, group, levels[group]);
+			}
 			if (to_stderr)
 			{
 				file_logger->set_level(file_logger, group, levels[group]);
 			}
 		}
-		charon->bus->add_logger(charon->bus, &sys_logger->logger);
+		if (sys_logger)
+		{
+			charon->bus->add_logger(charon->bus, &sys_logger->logger);
+		}
 		charon->bus->add_logger(charon->bus, &file_logger->logger);
 
 		sys_logger = add_sys_logger(this, "auth", current_loggers);
-		sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
-		charon->bus->add_logger(charon->bus, &sys_logger->logger);
+		if (sys_logger)
+		{
+			sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
+			charon->bus->add_logger(charon->bus, &sys_logger->logger);
+		}
 	}
 	/* unregister and destroy any unused remaining loggers */
 	current_loggers->destroy_function(current_loggers,
@@ -476,6 +495,53 @@ static void destroy(private_daemon_t *this)
 	free(this);
 }
 
+/**
+ * Run a set of configured scripts
+ */
+static void run_scripts(private_daemon_t *this, char *verb)
+{
+	enumerator_t *enumerator;
+	char *key, *value, *pos, buf[1024];
+	FILE *cmd;
+
+	enumerator = lib->settings->create_key_value_enumerator(lib->settings,
+												"%s.%s-scripts", lib->ns, verb);
+	while (enumerator->enumerate(enumerator, &key, &value))
+	{
+		DBG1(DBG_DMN, "executing %s script '%s' (%s):", verb, key, value);
+		cmd = popen(value, "r");
+		if (!cmd)
+		{
+			DBG1(DBG_DMN, "executing %s script '%s' (%s) failed: %s",
+				 verb, key, value, strerror(errno));
+			continue;
+		}
+		while (TRUE)
+		{
+			if (!fgets(buf, sizeof(buf), cmd))
+			{
+				if (ferror(cmd))
+				{
+					DBG1(DBG_DMN, "reading from %s script '%s' (%s) failed",
+						 verb, key, value);
+				}
+				break;
+			}
+			else
+			{
+				pos = buf + strlen(buf);
+				if (pos > buf && pos[-1] == '\n')
+				{
+					pos[-1] = '\0';
+				}
+				DBG1(DBG_DMN, "%s: %s", key, buf);
+			}
+		}
+		pclose(cmd);
+	}
+	enumerator->destroy(enumerator);
+}
+
 METHOD(daemon_t, start, void,
 	   private_daemon_t *this)
 {
@@ -483,6 +549,8 @@ METHOD(daemon_t, start, void,
 	lib->processor->set_threads(lib->processor,
 						lib->settings->get_int(lib->settings, "%s.threads",
 											   DEFAULT_THREADS, lib->ns));
+
+	run_scripts(this, "start");
 }
 
 
@@ -598,6 +666,8 @@ void libcharon_deinit()
 		return;
 	}
 
+	run_scripts(this, "stop");
+
 	destroy(this);
 	charon = NULL;
 }
diff --git a/src/libcharon/encoding/generator.c b/src/libcharon/encoding/generator.c
index 2b6825c..a0a508f 100644
--- a/src/libcharon/encoding/generator.c
+++ b/src/libcharon/encoding/generator.c
@@ -17,7 +17,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <arpa/inet.h>
 #include <stdio.h>
 
 #include "generator.h"
@@ -498,15 +497,15 @@ METHOD(generator_t, generate_payload, void,
 			case ENCRYPTED_DATA:
 				generate_from_chunk(this, rules[i].offset);
 				break;
-			case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
-			case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
-			case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
-			case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
-			case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
-			case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
-			case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
-			case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
-			case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV2_TRANSFORM_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV1_TRANSFORM_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV2_CONFIGURATION_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV1_CONFIGURATION_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE:
 			{
 				linked_list_t *proposals;
 				enumerator_t *enumerator;
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 11e735a..0f5f40a 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -89,7 +89,7 @@ typedef struct {
 typedef struct {
 	/** payload type */
 	payload_type_t type;
-	/** notify type, if payload == NOTIFY */
+	/** notify type, if payload == PLV2_NOTIFY */
 	notify_type_t notify;
 } payload_order_t;
 
@@ -120,11 +120,11 @@ typedef struct {
  */
 static payload_rule_t ike_sa_init_i_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
-	{SECURITY_ASSOCIATION,			1,	1,						FALSE,	FALSE},
-	{KEY_EXCHANGE,					1,	1,						FALSE,	FALSE},
-	{NONCE,							1,	1,						FALSE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
+	{PLV2_SECURITY_ASSOCIATION,		1,	1,						FALSE,	FALSE},
+	{PLV2_KEY_EXCHANGE,				1,	1,						FALSE,	FALSE},
+	{PLV2_NONCE,					1,	1,						FALSE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
 };
 
 /**
@@ -132,14 +132,14 @@ static payload_rule_t ike_sa_init_i_rules[] = {
  */
 static payload_order_t ike_sa_init_i_order[] = {
 /*	payload type					notify type */
-	{NOTIFY,						COOKIE},
-	{SECURITY_ASSOCIATION,			0},
-	{KEY_EXCHANGE,					0},
-	{NONCE,							0},
-	{NOTIFY,						NAT_DETECTION_SOURCE_IP},
-	{NOTIFY,						NAT_DETECTION_DESTINATION_IP},
-	{NOTIFY,						0},
-	{VENDOR_ID,						0},
+	{PLV2_NOTIFY,					COOKIE},
+	{PLV2_SECURITY_ASSOCIATION,		0},
+	{PLV2_KEY_EXCHANGE,				0},
+	{PLV2_NONCE,					0},
+	{PLV2_NOTIFY,					NAT_DETECTION_SOURCE_IP},
+	{PLV2_NOTIFY,					NAT_DETECTION_DESTINATION_IP},
+	{PLV2_NOTIFY,					0},
+	{PLV2_VENDOR_ID,				0},
 };
 
 /**
@@ -147,12 +147,12 @@ static payload_order_t ike_sa_init_i_order[] = {
  */
 static payload_rule_t ike_sa_init_r_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	FALSE,	TRUE},
-	{SECURITY_ASSOCIATION,			1,	1,						FALSE,	FALSE},
-	{KEY_EXCHANGE,					1,	1,						FALSE,	FALSE},
-	{NONCE,							1,	1,						FALSE,	FALSE},
-	{CERTIFICATE_REQUEST,			0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	TRUE},
+	{PLV2_SECURITY_ASSOCIATION,		1,	1,						FALSE,	FALSE},
+	{PLV2_KEY_EXCHANGE,				1,	1,						FALSE,	FALSE},
+	{PLV2_NONCE,					1,	1,						FALSE,	FALSE},
+	{PLV2_CERTREQ,					0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
 };
 
 /**
@@ -160,15 +160,15 @@ static payload_rule_t ike_sa_init_r_rules[] = {
  */
 static payload_order_t ike_sa_init_r_order[] = {
 /*	payload type					notify type */
-	{SECURITY_ASSOCIATION,			0},
-	{KEY_EXCHANGE,					0},
-	{NONCE,							0},
-	{NOTIFY,						NAT_DETECTION_SOURCE_IP},
-	{NOTIFY,						NAT_DETECTION_DESTINATION_IP},
-	{NOTIFY,						HTTP_CERT_LOOKUP_SUPPORTED},
-	{CERTIFICATE_REQUEST,			0},
-	{NOTIFY,						0},
-	{VENDOR_ID,						0},
+	{PLV2_SECURITY_ASSOCIATION,		0},
+	{PLV2_KEY_EXCHANGE,				0},
+	{PLV2_NONCE,					0},
+	{PLV2_NOTIFY,					NAT_DETECTION_SOURCE_IP},
+	{PLV2_NOTIFY,					NAT_DETECTION_DESTINATION_IP},
+	{PLV2_NOTIFY,					HTTP_CERT_LOOKUP_SUPPORTED},
+	{PLV2_CERTREQ,					0},
+	{PLV2_NOTIFY,					0},
+	{PLV2_VENDOR_ID,				0},
 };
 
 /**
@@ -176,24 +176,24 @@ static payload_order_t ike_sa_init_r_order[] = {
  */
 static payload_rule_t ike_auth_i_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{EXTENSIBLE_AUTHENTICATION,		0,	1,						TRUE,	TRUE},
-	{AUTHENTICATION,				0,	1,						TRUE,	TRUE},
-	{ID_INITIATOR,					0,	1,						TRUE,	FALSE},
-	{CERTIFICATE,					0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
-	{CERTIFICATE_REQUEST,			0,	MAX_CERTREQ_PAYLOADS,	TRUE,	FALSE},
-	{ID_RESPONDER,					0,	1,						TRUE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV2_EAP,						0,	1,						TRUE,	TRUE},
+	{PLV2_AUTH,						0,	1,						TRUE,	TRUE},
+	{PLV2_ID_INITIATOR,				0,	1,						TRUE,	FALSE},
+	{PLV2_CERTIFICATE,				0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_CERTREQ,					0,	MAX_CERTREQ_PAYLOADS,	TRUE,	FALSE},
+	{PLV2_ID_RESPONDER,				0,	1,						TRUE,	FALSE},
 #ifdef ME
-	{SECURITY_ASSOCIATION,			0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_INITIATOR,	0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_RESPONDER,	0,	1,						TRUE,	FALSE},
+	{PLV2_SECURITY_ASSOCIATION,		0,	1,						TRUE,	FALSE},
+	{PLV2_TS_INITIATOR,				0,	1,						TRUE,	FALSE},
+	{PLV2_TS_RESPONDER,				0,	1,						TRUE,	FALSE},
 #else
-	{SECURITY_ASSOCIATION,			0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_INITIATOR,	0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_RESPONDER,	0,	1,						TRUE,	FALSE},
+	{PLV2_SECURITY_ASSOCIATION,		0,	1,						TRUE,	FALSE},
+	{PLV2_TS_INITIATOR,				0,	1,						TRUE,	FALSE},
+	{PLV2_TS_RESPONDER,				0,	1,						TRUE,	FALSE},
 #endif /* ME */
-	{CONFIGURATION,					0,	1,						TRUE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_CONFIGURATION,			0,	1,						TRUE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
@@ -201,28 +201,28 @@ static payload_rule_t ike_auth_i_rules[] = {
  */
 static payload_order_t ike_auth_i_order[] = {
 /*	payload type					notify type */
-	{ID_INITIATOR,					0},
-	{CERTIFICATE,					0},
-	{NOTIFY,						INITIAL_CONTACT},
-	{NOTIFY,						HTTP_CERT_LOOKUP_SUPPORTED},
-	{CERTIFICATE_REQUEST,			0},
-	{ID_RESPONDER,					0},
-	{AUTHENTICATION,				0},
-	{EXTENSIBLE_AUTHENTICATION,		0},
-	{CONFIGURATION,					0},
-	{NOTIFY,						IPCOMP_SUPPORTED},
-	{NOTIFY,						USE_TRANSPORT_MODE},
-	{NOTIFY,						ESP_TFC_PADDING_NOT_SUPPORTED},
-	{NOTIFY,						NON_FIRST_FRAGMENTS_ALSO},
-	{SECURITY_ASSOCIATION,			0},
-	{TRAFFIC_SELECTOR_INITIATOR,	0},
-	{TRAFFIC_SELECTOR_RESPONDER,	0},
-	{NOTIFY,						MOBIKE_SUPPORTED},
-	{NOTIFY,						ADDITIONAL_IP4_ADDRESS},
-	{NOTIFY,						ADDITIONAL_IP6_ADDRESS},
-	{NOTIFY,						NO_ADDITIONAL_ADDRESSES},
-	{NOTIFY,						0},
-	{VENDOR_ID,						0},
+	{PLV2_ID_INITIATOR,				0},
+	{PLV2_CERTIFICATE,				0},
+	{PLV2_NOTIFY,					INITIAL_CONTACT},
+	{PLV2_NOTIFY,					HTTP_CERT_LOOKUP_SUPPORTED},
+	{PLV2_CERTREQ,					0},
+	{PLV2_ID_RESPONDER,				0},
+	{PLV2_AUTH,						0},
+	{PLV2_EAP,						0},
+	{PLV2_CONFIGURATION,			0},
+	{PLV2_NOTIFY,					IPCOMP_SUPPORTED},
+	{PLV2_NOTIFY,					USE_TRANSPORT_MODE},
+	{PLV2_NOTIFY,					ESP_TFC_PADDING_NOT_SUPPORTED},
+	{PLV2_NOTIFY,					NON_FIRST_FRAGMENTS_ALSO},
+	{PLV2_SECURITY_ASSOCIATION,		0},
+	{PLV2_TS_INITIATOR,				0},
+	{PLV2_TS_RESPONDER,				0},
+	{PLV2_NOTIFY,					MOBIKE_SUPPORTED},
+	{PLV2_NOTIFY,					ADDITIONAL_IP4_ADDRESS},
+	{PLV2_NOTIFY,					ADDITIONAL_IP6_ADDRESS},
+	{PLV2_NOTIFY,					NO_ADDITIONAL_ADDRESSES},
+	{PLV2_NOTIFY,					0},
+	{PLV2_VENDOR_ID,				0},
 };
 
 /**
@@ -230,16 +230,16 @@ static payload_order_t ike_auth_i_order[] = {
  */
 static payload_rule_t ike_auth_r_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
-	{EXTENSIBLE_AUTHENTICATION,		0,	1,						TRUE,	TRUE},
-	{AUTHENTICATION,				0,	1,						TRUE,	TRUE},
-	{CERTIFICATE,					0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
-	{ID_RESPONDER,					0,	1,						TRUE,	FALSE},
-	{SECURITY_ASSOCIATION,			0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_INITIATOR,	0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_RESPONDER,	0,	1,						TRUE,	FALSE},
-	{CONFIGURATION,					0,	1,						TRUE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
+	{PLV2_EAP,						0,	1,						TRUE,	TRUE},
+	{PLV2_AUTH,						0,	1,						TRUE,	TRUE},
+	{PLV2_CERTIFICATE,				0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_ID_RESPONDER,				0,	1,						TRUE,	FALSE},
+	{PLV2_SECURITY_ASSOCIATION,		0,	1,						TRUE,	FALSE},
+	{PLV2_TS_INITIATOR,				0,	1,						TRUE,	FALSE},
+	{PLV2_TS_RESPONDER,				0,	1,						TRUE,	FALSE},
+	{PLV2_CONFIGURATION,			0,	1,						TRUE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
@@ -247,25 +247,25 @@ static payload_rule_t ike_auth_r_rules[] = {
  */
 static payload_order_t ike_auth_r_order[] = {
 /*	payload type					notify type */
-	{ID_RESPONDER,					0},
-	{CERTIFICATE,					0},
-	{AUTHENTICATION,				0},
-	{EXTENSIBLE_AUTHENTICATION,		0},
-	{CONFIGURATION,					0},
-	{NOTIFY,						IPCOMP_SUPPORTED},
-	{NOTIFY,						USE_TRANSPORT_MODE},
-	{NOTIFY,						ESP_TFC_PADDING_NOT_SUPPORTED},
-	{NOTIFY,						NON_FIRST_FRAGMENTS_ALSO},
-	{SECURITY_ASSOCIATION,			0},
-	{TRAFFIC_SELECTOR_INITIATOR,	0},
-	{TRAFFIC_SELECTOR_RESPONDER,	0},
-	{NOTIFY,						AUTH_LIFETIME},
-	{NOTIFY,						MOBIKE_SUPPORTED},
-	{NOTIFY,						ADDITIONAL_IP4_ADDRESS},
-	{NOTIFY,						ADDITIONAL_IP6_ADDRESS},
-	{NOTIFY,						NO_ADDITIONAL_ADDRESSES},
-	{NOTIFY,						0},
-	{VENDOR_ID,						0},
+	{PLV2_ID_RESPONDER,				0},
+	{PLV2_CERTIFICATE,				0},
+	{PLV2_AUTH,						0},
+	{PLV2_EAP,						0},
+	{PLV2_CONFIGURATION,			0},
+	{PLV2_NOTIFY,					IPCOMP_SUPPORTED},
+	{PLV2_NOTIFY,					USE_TRANSPORT_MODE},
+	{PLV2_NOTIFY,					ESP_TFC_PADDING_NOT_SUPPORTED},
+	{PLV2_NOTIFY,					NON_FIRST_FRAGMENTS_ALSO},
+	{PLV2_SECURITY_ASSOCIATION,		0},
+	{PLV2_TS_INITIATOR,				0},
+	{PLV2_TS_RESPONDER,				0},
+	{PLV2_NOTIFY,					AUTH_LIFETIME},
+	{PLV2_NOTIFY,					MOBIKE_SUPPORTED},
+	{PLV2_NOTIFY,					ADDITIONAL_IP4_ADDRESS},
+	{PLV2_NOTIFY,					ADDITIONAL_IP6_ADDRESS},
+	{PLV2_NOTIFY,					NO_ADDITIONAL_ADDRESSES},
+	{PLV2_NOTIFY,					0},
+	{PLV2_VENDOR_ID,				0},
 };
 
 /**
@@ -273,10 +273,10 @@ static payload_order_t ike_auth_r_order[] = {
  */
 static payload_rule_t informational_i_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{CONFIGURATION,					0,	1,						TRUE,	FALSE},
-	{DELETE,						0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV2_CONFIGURATION,			0,	1,						TRUE,	FALSE},
+	{PLV2_DELETE,					0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
@@ -284,13 +284,13 @@ static payload_rule_t informational_i_rules[] = {
  */
 static payload_order_t informational_i_order[] = {
 /*	payload type					notify type */
-	{NOTIFY,						UPDATE_SA_ADDRESSES},
-	{NOTIFY,						NAT_DETECTION_SOURCE_IP},
-	{NOTIFY,						NAT_DETECTION_DESTINATION_IP},
-	{NOTIFY,						COOKIE2},
-	{NOTIFY,						0},
-	{DELETE,						0},
-	{CONFIGURATION,					0},
+	{PLV2_NOTIFY,					UPDATE_SA_ADDRESSES},
+	{PLV2_NOTIFY,					NAT_DETECTION_SOURCE_IP},
+	{PLV2_NOTIFY,					NAT_DETECTION_DESTINATION_IP},
+	{PLV2_NOTIFY,					COOKIE2},
+	{PLV2_NOTIFY,					0},
+	{PLV2_DELETE,					0},
+	{PLV2_CONFIGURATION,			0},
 };
 
 /**
@@ -298,10 +298,10 @@ static payload_order_t informational_i_order[] = {
  */
 static payload_rule_t informational_r_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{CONFIGURATION,					0,	1,						TRUE,	FALSE},
-	{DELETE,						0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV2_CONFIGURATION,			0,	1,						TRUE,	FALSE},
+	{PLV2_DELETE,					0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
@@ -309,13 +309,13 @@ static payload_rule_t informational_r_rules[] = {
  */
 static payload_order_t informational_r_order[] = {
 /*	payload type					notify type */
-	{NOTIFY,						UPDATE_SA_ADDRESSES},
-	{NOTIFY,						NAT_DETECTION_SOURCE_IP},
-	{NOTIFY,						NAT_DETECTION_DESTINATION_IP},
-	{NOTIFY,						COOKIE2},
-	{NOTIFY,						0},
-	{DELETE,						0},
-	{CONFIGURATION,					0},
+	{PLV2_NOTIFY,					UPDATE_SA_ADDRESSES},
+	{PLV2_NOTIFY,					NAT_DETECTION_SOURCE_IP},
+	{PLV2_NOTIFY,					NAT_DETECTION_DESTINATION_IP},
+	{PLV2_NOTIFY,					COOKIE2},
+	{PLV2_NOTIFY,					0},
+	{PLV2_DELETE,					0},
+	{PLV2_CONFIGURATION,			0},
 };
 
 /**
@@ -323,14 +323,14 @@ static payload_order_t informational_r_order[] = {
  */
 static payload_rule_t create_child_sa_i_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{SECURITY_ASSOCIATION,			1,	1,						TRUE,	FALSE},
-	{NONCE,							1,	1,						TRUE,	FALSE},
-	{KEY_EXCHANGE,					0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_INITIATOR,	0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_RESPONDER,	0,	1,						TRUE,	FALSE},
-	{CONFIGURATION,					0,	1,						TRUE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV2_SECURITY_ASSOCIATION,		1,	1,						TRUE,	FALSE},
+	{PLV2_NONCE,					1,	1,						TRUE,	FALSE},
+	{PLV2_KEY_EXCHANGE,				0,	1,						TRUE,	FALSE},
+	{PLV2_TS_INITIATOR,				0,	1,						TRUE,	FALSE},
+	{PLV2_TS_RESPONDER,				0,	1,						TRUE,	FALSE},
+	{PLV2_CONFIGURATION,			0,	1,						TRUE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
@@ -338,17 +338,17 @@ static payload_rule_t create_child_sa_i_rules[] = {
  */
 static payload_order_t create_child_sa_i_order[] = {
 /*	payload type					notify type */
-	{NOTIFY,						REKEY_SA},
-	{NOTIFY,						IPCOMP_SUPPORTED},
-	{NOTIFY,						USE_TRANSPORT_MODE},
-	{NOTIFY,						ESP_TFC_PADDING_NOT_SUPPORTED},
-	{NOTIFY,						NON_FIRST_FRAGMENTS_ALSO},
-	{SECURITY_ASSOCIATION,			0},
-	{NONCE,							0},
-	{KEY_EXCHANGE,					0},
-	{TRAFFIC_SELECTOR_INITIATOR,	0},
-	{TRAFFIC_SELECTOR_RESPONDER,	0},
-	{NOTIFY,						0},
+	{PLV2_NOTIFY,					REKEY_SA},
+	{PLV2_NOTIFY,					IPCOMP_SUPPORTED},
+	{PLV2_NOTIFY,					USE_TRANSPORT_MODE},
+	{PLV2_NOTIFY,					ESP_TFC_PADDING_NOT_SUPPORTED},
+	{PLV2_NOTIFY,					NON_FIRST_FRAGMENTS_ALSO},
+	{PLV2_SECURITY_ASSOCIATION,		0},
+	{PLV2_NONCE,					0},
+	{PLV2_KEY_EXCHANGE,				0},
+	{PLV2_TS_INITIATOR,				0},
+	{PLV2_TS_RESPONDER,				0},
+	{PLV2_NOTIFY,					0},
 };
 
 /**
@@ -356,14 +356,14 @@ static payload_order_t create_child_sa_i_order[] = {
  */
 static payload_rule_t create_child_sa_r_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
-	{SECURITY_ASSOCIATION,			1,	1,						TRUE,	FALSE},
-	{NONCE,							1,	1,						TRUE,	FALSE},
-	{KEY_EXCHANGE,					0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_INITIATOR,	0,	1,						TRUE,	FALSE},
-	{TRAFFIC_SELECTOR_RESPONDER,	0,	1,						TRUE,	FALSE},
-	{CONFIGURATION,					0,	1,						TRUE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
+	{PLV2_SECURITY_ASSOCIATION,		1,	1,						TRUE,	FALSE},
+	{PLV2_NONCE,					1,	1,						TRUE,	FALSE},
+	{PLV2_KEY_EXCHANGE,				0,	1,						TRUE,	FALSE},
+	{PLV2_TS_INITIATOR,				0,	1,						TRUE,	FALSE},
+	{PLV2_TS_RESPONDER,				0,	1,						TRUE,	FALSE},
+	{PLV2_CONFIGURATION,			0,	1,						TRUE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
@@ -371,17 +371,17 @@ static payload_rule_t create_child_sa_r_rules[] = {
  */
 static payload_order_t create_child_sa_r_order[] = {
 /*	payload type					notify type */
-	{NOTIFY,						IPCOMP_SUPPORTED},
-	{NOTIFY,						USE_TRANSPORT_MODE},
-	{NOTIFY,						ESP_TFC_PADDING_NOT_SUPPORTED},
-	{NOTIFY,						NON_FIRST_FRAGMENTS_ALSO},
-	{SECURITY_ASSOCIATION,			0},
-	{NONCE,							0},
-	{KEY_EXCHANGE,					0},
-	{TRAFFIC_SELECTOR_INITIATOR,	0},
-	{TRAFFIC_SELECTOR_RESPONDER,	0},
-	{NOTIFY,						ADDITIONAL_TS_POSSIBLE},
-	{NOTIFY,						0},
+	{PLV2_NOTIFY,					IPCOMP_SUPPORTED},
+	{PLV2_NOTIFY,					USE_TRANSPORT_MODE},
+	{PLV2_NOTIFY,					ESP_TFC_PADDING_NOT_SUPPORTED},
+	{PLV2_NOTIFY,					NON_FIRST_FRAGMENTS_ALSO},
+	{PLV2_SECURITY_ASSOCIATION,		0},
+	{PLV2_NONCE,					0},
+	{PLV2_KEY_EXCHANGE,				0},
+	{PLV2_TS_INITIATOR,				0},
+	{PLV2_TS_RESPONDER,				0},
+	{PLV2_NOTIFY,					ADDITIONAL_TS_POSSIBLE},
+	{PLV2_NOTIFY,					0},
 };
 
 #ifdef ME
@@ -390,9 +390,9 @@ static payload_order_t create_child_sa_r_order[] = {
  */
 static payload_rule_t me_connect_i_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
-	{ID_PEER,						1,	1,						TRUE,	FALSE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE}
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
+	{PLV2_ID_PEER,					1,	1,						TRUE,	FALSE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE}
 };
 
 /**
@@ -400,9 +400,9 @@ static payload_rule_t me_connect_i_rules[] = {
  */
 static payload_order_t me_connect_i_order[] = {
 /*	payload type					notify type */
-	{NOTIFY,						0},
-	{ID_PEER,						0},
-	{VENDOR_ID,						0},
+	{PLV2_NOTIFY,					0},
+	{PLV2_ID_PEER,					0},
+	{PLV2_VENDOR_ID,				0},
 };
 
 /**
@@ -410,8 +410,8 @@ static payload_order_t me_connect_i_order[] = {
  */
 static payload_rule_t me_connect_r_rules[] = {
 /*	payload type					min	max						encr	suff */
-	{NOTIFY,						0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
-	{VENDOR_ID,						0,	MAX_VID_PAYLOADS,		TRUE,	FALSE}
+	{PLV2_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	TRUE},
+	{PLV2_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE}
 };
 
 /**
@@ -419,8 +419,8 @@ static payload_rule_t me_connect_r_rules[] = {
  */
 static payload_order_t me_connect_r_order[] = {
 /*	payload type					notify type */
-	{NOTIFY,						0},
-	{VENDOR_ID,						0},
+	{PLV2_NOTIFY,					0},
+	{PLV2_VENDOR_ID,				0},
 };
 #endif /* ME */
 
@@ -429,284 +429,284 @@ static payload_order_t me_connect_r_order[] = {
  * Message rule for ID_PROT from initiator.
  */
 static payload_rule_t id_prot_i_rules[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
-	{SECURITY_ASSOCIATION_V1,	0,	1,						FALSE,	FALSE},
-	{KEY_EXCHANGE_V1,			0,	1,						FALSE,	FALSE},
-	{NONCE_V1,					0,	1,						FALSE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
-	{CERTIFICATE_REQUEST_V1,	0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
-	{NAT_D_V1,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{NAT_D_DRAFT_00_03_V1,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{ID_V1,						0,	1,						TRUE,	FALSE},
-	{CERTIFICATE_V1,			0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
-	{SIGNATURE_V1,				0,	1,						TRUE,	FALSE},
-	{HASH_V1,					0,	1,						TRUE,	FALSE},
-	{FRAGMENT_V1,				0,	1,						FALSE,	TRUE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_SECURITY_ASSOCIATION,		0,	1,						FALSE,	FALSE},
+	{PLV1_KEY_EXCHANGE,				0,	1,						FALSE,	FALSE},
+	{PLV1_NONCE,					0,	1,						FALSE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_CERTREQ,					0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_NAT_D,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_NAT_D_DRAFT_00_03,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_ID,						0,	1,						TRUE,	FALSE},
+	{PLV1_CERTIFICATE,				0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
+	{PLV1_SIGNATURE,				0,	1,						TRUE,	FALSE},
+	{PLV1_HASH,						0,	1,						TRUE,	FALSE},
+	{PLV1_FRAGMENT,					0,	1,						FALSE,	TRUE},
 };
 
 /**
  * payload order for ID_PROT from initiator.
  */
 static payload_order_t id_prot_i_order[] = {
-/*	payload type				notify type */
-	{SECURITY_ASSOCIATION_V1,	0},
-	{KEY_EXCHANGE_V1,			0},
-	{NONCE_V1,					0},
-	{ID_V1,						0},
-	{CERTIFICATE_V1,			0},
-	{SIGNATURE_V1,				0},
-	{HASH_V1,					0},
-	{CERTIFICATE_REQUEST_V1,	0},
-	{NOTIFY_V1,					0},
-	{VENDOR_ID_V1,				0},
-	{NAT_D_V1,					0},
-	{NAT_D_DRAFT_00_03_V1,		0},
-	{FRAGMENT_V1,				0},
+/*	payload type					notify type */
+	{PLV1_SECURITY_ASSOCIATION,		0},
+	{PLV1_KEY_EXCHANGE,				0},
+	{PLV1_NONCE,					0},
+	{PLV1_ID,						0},
+	{PLV1_CERTIFICATE,				0},
+	{PLV1_SIGNATURE,				0},
+	{PLV1_HASH,						0},
+	{PLV1_CERTREQ,					0},
+	{PLV1_NOTIFY,					0},
+	{PLV1_VENDOR_ID,				0},
+	{PLV1_NAT_D,					0},
+	{PLV1_NAT_D_DRAFT_00_03,		0},
+	{PLV1_FRAGMENT,					0},
 };
 
 /**
  * Message rule for ID_PROT from responder.
  */
 static payload_rule_t id_prot_r_rules[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
-	{SECURITY_ASSOCIATION_V1,	0,	1,						FALSE,	FALSE},
-	{KEY_EXCHANGE_V1,			0,	1,						FALSE,	FALSE},
-	{NONCE_V1,					0,	1,						FALSE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
-	{CERTIFICATE_REQUEST_V1,	0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
-	{NAT_D_V1,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{NAT_D_DRAFT_00_03_V1,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{ID_V1,						0,	1,						TRUE,	FALSE},
-	{CERTIFICATE_V1,			0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
-	{SIGNATURE_V1,				0,	1,						TRUE,	FALSE},
-	{HASH_V1,					0,	1,						TRUE,	FALSE},
-	{FRAGMENT_V1,				0,	1,						FALSE,	TRUE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_SECURITY_ASSOCIATION,		0,	1,						FALSE,	FALSE},
+	{PLV1_KEY_EXCHANGE,				0,	1,						FALSE,	FALSE},
+	{PLV1_NONCE,					0,	1,						FALSE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_CERTREQ,					0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_NAT_D,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_NAT_D_DRAFT_00_03,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_ID,						0,	1,						TRUE,	FALSE},
+	{PLV1_CERTIFICATE,				0,	MAX_CERT_PAYLOADS,		TRUE,	FALSE},
+	{PLV1_SIGNATURE,				0,	1,						TRUE,	FALSE},
+	{PLV1_HASH,						0,	1,						TRUE,	FALSE},
+	{PLV1_FRAGMENT,					0,	1,						FALSE,	TRUE},
 };
 
 /**
  * payload order for ID_PROT from responder.
  */
 static payload_order_t id_prot_r_order[] = {
-/*	payload type				notify type */
-	{SECURITY_ASSOCIATION_V1,	0},
-	{KEY_EXCHANGE_V1,			0},
-	{NONCE_V1,					0},
-	{ID_V1,						0},
-	{CERTIFICATE_V1,			0},
-	{SIGNATURE_V1,				0},
-	{HASH_V1,					0},
-	{CERTIFICATE_REQUEST_V1,	0},
-	{NOTIFY_V1,					0},
-	{VENDOR_ID_V1,				0},
-	{NAT_D_V1,					0},
-	{NAT_D_DRAFT_00_03_V1,		0},
-	{FRAGMENT_V1,				0},
+/*	payload type					notify type */
+	{PLV1_SECURITY_ASSOCIATION,		0},
+	{PLV1_KEY_EXCHANGE,				0},
+	{PLV1_NONCE,					0},
+	{PLV1_ID,						0},
+	{PLV1_CERTIFICATE,				0},
+	{PLV1_SIGNATURE,				0},
+	{PLV1_HASH,						0},
+	{PLV1_CERTREQ,					0},
+	{PLV1_NOTIFY,					0},
+	{PLV1_VENDOR_ID,				0},
+	{PLV1_NAT_D,					0},
+	{PLV1_NAT_D_DRAFT_00_03,		0},
+	{PLV1_FRAGMENT,					0},
 };
 
 /**
  * Message rule for AGGRESSIVE from initiator.
  */
 static payload_rule_t aggressive_i_rules[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
-	{SECURITY_ASSOCIATION_V1,	0,	1,						FALSE,	FALSE},
-	{KEY_EXCHANGE_V1,			0,	1,						FALSE,	FALSE},
-	{NONCE_V1,					0,	1,						FALSE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
-	{CERTIFICATE_REQUEST_V1,	0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
-	{NAT_D_V1,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{NAT_D_DRAFT_00_03_V1,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{ID_V1,						0,	1,						FALSE,	FALSE},
-	{CERTIFICATE_V1,			0,	1,						TRUE,	FALSE},
-	{SIGNATURE_V1,				0,	1,						TRUE,	FALSE},
-	{HASH_V1,					0,	1,						TRUE,	FALSE},
-	{FRAGMENT_V1,				0,	1,						FALSE,	TRUE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_SECURITY_ASSOCIATION,		0,	1,						FALSE,	FALSE},
+	{PLV1_KEY_EXCHANGE,				0,	1,						FALSE,	FALSE},
+	{PLV1_NONCE,					0,	1,						FALSE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_CERTREQ,					0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_NAT_D,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_NAT_D_DRAFT_00_03,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_ID,						0,	1,						FALSE,	FALSE},
+	{PLV1_CERTIFICATE,				0,	1,						TRUE,	FALSE},
+	{PLV1_SIGNATURE,				0,	1,						TRUE,	FALSE},
+	{PLV1_HASH,						0,	1,						TRUE,	FALSE},
+	{PLV1_FRAGMENT,					0,	1,						FALSE,	TRUE},
 };
 
 /**
  * payload order for AGGRESSIVE from initiator.
  */
 static payload_order_t aggressive_i_order[] = {
-/*	payload type				notify type */
-	{SECURITY_ASSOCIATION_V1,	0},
-	{KEY_EXCHANGE_V1,			0},
-	{NONCE_V1,					0},
-	{ID_V1,						0},
-	{CERTIFICATE_V1,			0},
-	{NAT_D_V1,					0},
-	{NAT_D_DRAFT_00_03_V1,		0},
-	{SIGNATURE_V1,				0},
-	{HASH_V1,					0},
-	{CERTIFICATE_REQUEST_V1,	0},
-	{NOTIFY_V1,					0},
-	{VENDOR_ID_V1,				0},
-	{FRAGMENT_V1,				0},
+/*	payload type					notify type */
+	{PLV1_SECURITY_ASSOCIATION,		0},
+	{PLV1_KEY_EXCHANGE,				0},
+	{PLV1_NONCE,					0},
+	{PLV1_ID,						0},
+	{PLV1_CERTIFICATE,				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},
 };
 
 /**
  * Message rule for AGGRESSIVE from responder.
  */
 static payload_rule_t aggressive_r_rules[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
-	{SECURITY_ASSOCIATION_V1,	0,	1,						FALSE,	FALSE},
-	{KEY_EXCHANGE_V1,			0,	1,						FALSE,	FALSE},
-	{NONCE_V1,					0,	1,						FALSE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
-	{CERTIFICATE_REQUEST_V1,	0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
-	{NAT_D_V1,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{NAT_D_DRAFT_00_03_V1,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
-	{ID_V1,						0,	1,						FALSE,	FALSE},
-	{CERTIFICATE_V1,			0,	1,						FALSE,	FALSE},
-	{SIGNATURE_V1,				0,	1,						FALSE,	FALSE},
-	{HASH_V1,					0,	1,						FALSE,	FALSE},
-	{FRAGMENT_V1,				0,	1,						FALSE,	TRUE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_SECURITY_ASSOCIATION,		0,	1,						FALSE,	FALSE},
+	{PLV1_KEY_EXCHANGE,				0,	1,						FALSE,	FALSE},
+	{PLV1_NONCE,					0,	1,						FALSE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_CERTREQ,					0,	MAX_CERTREQ_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_NAT_D,					0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_NAT_D_DRAFT_00_03,		0,	MAX_NAT_D_PAYLOADS,		FALSE,	FALSE},
+	{PLV1_ID,						0,	1,						FALSE,	FALSE},
+	{PLV1_CERTIFICATE,				0,	1,						FALSE,	FALSE},
+	{PLV1_SIGNATURE,				0,	1,						FALSE,	FALSE},
+	{PLV1_HASH,						0,	1,						FALSE,	FALSE},
+	{PLV1_FRAGMENT,					0,	1,						FALSE,	TRUE},
 };
 
 /**
  * payload order for AGGRESSIVE from responder.
  */
 static payload_order_t aggressive_r_order[] = {
-/*	payload type				notify type */
-	{SECURITY_ASSOCIATION_V1,	0},
-	{KEY_EXCHANGE_V1,			0},
-	{NONCE_V1,					0},
-	{ID_V1,						0},
-	{CERTIFICATE_V1,			0},
-	{NAT_D_V1,					0},
-	{NAT_D_DRAFT_00_03_V1,		0},
-	{SIGNATURE_V1,				0},
-	{HASH_V1,					0},
-	{CERTIFICATE_REQUEST_V1,	0},
-	{NOTIFY_V1,					0},
-	{VENDOR_ID_V1,				0},
-	{FRAGMENT_V1,				0},
+/*	payload type					notify type */
+	{PLV1_SECURITY_ASSOCIATION,		0},
+	{PLV1_KEY_EXCHANGE,				0},
+	{PLV1_NONCE,					0},
+	{PLV1_ID,						0},
+	{PLV1_CERTIFICATE,				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},
 };
 
 /**
  * Message rule for INFORMATIONAL_V1 from initiator.
  */
 static payload_rule_t informational_i_rules_v1[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{DELETE_V1,					0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV1_DELETE,					0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
  * payload order for INFORMATIONAL_V1 from initiator.
  */
 static payload_order_t informational_i_order_v1[] = {
-/*	payload type				notify type */
-	{NOTIFY_V1,					0},
-	{DELETE_V1,					0},
-	{VENDOR_ID_V1,				0},
+/*	payload type					notify type */
+	{PLV1_NOTIFY,					0},
+	{PLV1_DELETE,					0},
+	{PLV1_VENDOR_ID,				0},
 };
 
 /**
  * Message rule for INFORMATIONAL_V1 from responder.
  */
 static payload_rule_t informational_r_rules_v1[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{DELETE_V1,					0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	FALSE,	FALSE},
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV1_DELETE,					0,	MAX_DELETE_PAYLOADS,	TRUE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
 };
 
 /**
  * payload order for INFORMATIONAL_V1 from responder.
  */
 static payload_order_t informational_r_order_v1[] = {
-/*	payload type				notify type */
-	{NOTIFY_V1,					0},
-	{DELETE_V1,					0},
-	{VENDOR_ID_V1,				0},
+/*	payload type					notify type */
+	{PLV1_NOTIFY,					0},
+	{PLV1_DELETE,					0},
+	{PLV1_VENDOR_ID,				0},
 };
 
 /**
  * Message rule for QUICK_MODE from initiator.
  */
 static payload_rule_t quick_mode_i_rules[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
-	{HASH_V1,					0,	1,						TRUE,	FALSE},
-	{SECURITY_ASSOCIATION_V1,	0,	2,						TRUE,	FALSE},
-	{NONCE_V1,					0,	1,						TRUE,	FALSE},
-	{KEY_EXCHANGE_V1,			0,	1,						TRUE,	FALSE},
-	{ID_V1,						0,	2,						TRUE,	FALSE},
-	{NAT_OA_V1,					0,	2,						TRUE,	FALSE},
-	{NAT_OA_DRAFT_00_03_V1,		0,	2,						TRUE,	FALSE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV1_HASH,						0,	1,						TRUE,	FALSE},
+	{PLV1_SECURITY_ASSOCIATION,		0,	2,						TRUE,	FALSE},
+	{PLV1_NONCE,					0,	1,						TRUE,	FALSE},
+	{PLV1_KEY_EXCHANGE,				0,	1,						TRUE,	FALSE},
+	{PLV1_ID,						0,	2,						TRUE,	FALSE},
+	{PLV1_NAT_OA,					0,	2,						TRUE,	FALSE},
+	{PLV1_NAT_OA_DRAFT_00_03,		0,	2,						TRUE,	FALSE},
 };
 
 /**
  * payload order for QUICK_MODE from initiator.
  */
 static payload_order_t quick_mode_i_order[] = {
-/*	payload type				notify type */
-	{NOTIFY_V1,					0},
-	{VENDOR_ID_V1,				0},
-	{HASH_V1,					0},
-	{SECURITY_ASSOCIATION_V1,	0},
-	{NONCE_V1,					0},
-	{KEY_EXCHANGE_V1,			0},
-	{ID_V1,						0},
-	{NAT_OA_V1,					0},
-	{NAT_OA_DRAFT_00_03_V1,		0},
+/*	payload type					notify type */
+	{PLV1_NOTIFY,					0},
+	{PLV1_VENDOR_ID,				0},
+	{PLV1_HASH,						0},
+	{PLV1_SECURITY_ASSOCIATION,		0},
+	{PLV1_NONCE,					0},
+	{PLV1_KEY_EXCHANGE,				0},
+	{PLV1_ID,						0},
+	{PLV1_NAT_OA,					0},
+	{PLV1_NAT_OA_DRAFT_00_03,		0},
 };
 
 /**
  * Message rule for QUICK_MODE from responder.
  */
 static payload_rule_t quick_mode_r_rules[] = {
-/*	payload type				min	max						encr	suff */
-	{NOTIFY_V1,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
-	{VENDOR_ID_V1,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
-	{HASH_V1,					0,	1,						TRUE,	FALSE},
-	{SECURITY_ASSOCIATION_V1,	0,	2,						TRUE,	FALSE},
-	{NONCE_V1,					0,	1,						TRUE,	FALSE},
-	{KEY_EXCHANGE_V1,			0,	1,						TRUE,	FALSE},
-	{ID_V1,						0,	2,						TRUE,	FALSE},
-	{NAT_OA_V1,					0,	2,						TRUE,	FALSE},
-	{NAT_OA_DRAFT_00_03_V1,		0,	2,						TRUE,	FALSE},
+/*	payload type					min	max						encr	suff */
+	{PLV1_NOTIFY,					0,	MAX_NOTIFY_PAYLOADS,	TRUE,	FALSE},
+	{PLV1_VENDOR_ID,				0,	MAX_VID_PAYLOADS,		TRUE,	FALSE},
+	{PLV1_HASH,						0,	1,						TRUE,	FALSE},
+	{PLV1_SECURITY_ASSOCIATION,		0,	2,						TRUE,	FALSE},
+	{PLV1_NONCE,					0,	1,						TRUE,	FALSE},
+	{PLV1_KEY_EXCHANGE,				0,	1,						TRUE,	FALSE},
+	{PLV1_ID,						0,	2,						TRUE,	FALSE},
+	{PLV1_NAT_OA,					0,	2,						TRUE,	FALSE},
+	{PLV1_NAT_OA_DRAFT_00_03,		0,	2,						TRUE,	FALSE},
 };
 
 /**
  * payload order for QUICK_MODE from responder.
  */
 static payload_order_t quick_mode_r_order[] = {
-/*	payload type				notify type */
-	{NOTIFY_V1,					0},
-	{VENDOR_ID_V1,				0},
-	{HASH_V1,					0},
-	{SECURITY_ASSOCIATION_V1,	0},
-	{NONCE_V1,					0},
-	{KEY_EXCHANGE_V1,			0},
-	{ID_V1,						0},
-	{NAT_OA_V1,					0},
-	{NAT_OA_DRAFT_00_03_V1,		0},
+/*	payload type					notify type */
+	{PLV1_NOTIFY,					0},
+	{PLV1_VENDOR_ID,				0},
+	{PLV1_HASH,						0},
+	{PLV1_SECURITY_ASSOCIATION,		0},
+	{PLV1_NONCE,					0},
+	{PLV1_KEY_EXCHANGE,				0},
+	{PLV1_ID,						0},
+	{PLV1_NAT_OA,					0},
+	{PLV1_NAT_OA_DRAFT_00_03,		0},
 };
 
 /**
  * Message rule for TRANSACTION.
  */
 static payload_rule_t transaction_payload_rules_v1[] = {
-/*	payload type				min	max	encr	suff */
-	{HASH_V1,					0,	1,	TRUE,	FALSE},
-	{CONFIGURATION_V1,			1,	1,	FALSE,	FALSE},
+/*	payload type					min	max	encr	suff */
+	{PLV1_HASH,						0,	1,	TRUE,	FALSE},
+	{PLV1_CONFIGURATION,			1,	1,	FALSE,	FALSE},
 };
 
 /**
  * Payload order for TRANSACTION.
  */
 static payload_order_t transaction_payload_order_v1[] = {
-/*	payload type			notify type */
-	{HASH_V1,					0},
-	{CONFIGURATION_V1,			0},
+/*	payload type					notify type */
+	{PLV1_HASH,						0},
+	{PLV1_CONFIGURATION,			0},
 };
 
 #endif /* USE_IKEV1 */
@@ -1063,7 +1063,7 @@ METHOD(message_t, add_payload, void,
 	{
 		this->first_payload = payload->get_type(payload);
 	}
-	payload->set_next_type(payload, NO_PAYLOAD);
+	payload->set_next_type(payload, PL_NONE);
 	this->payloads->insert_last(this->payloads, payload);
 
 	DBG2(DBG_ENC ,"added payload of type %N to message",
@@ -1086,11 +1086,11 @@ METHOD(message_t, add_notify, void,
 	}
 	if (this->major_version == IKEV2_MAJOR_VERSION)
 	{
-		notify = notify_payload_create(NOTIFY);
+		notify = notify_payload_create(PLV2_NOTIFY);
 	}
 	else
 	{
-		notify = notify_payload_create(NOTIFY_V1);
+		notify = notify_payload_create(PLV1_NOTIFY);
 	}
 	notify->set_notify_type(notify, type);
 	notify->set_notification_data(notify, data);
@@ -1162,8 +1162,8 @@ METHOD(message_t, get_notify, notify_payload_t*,
 	enumerator = create_payload_enumerator(this);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY ||
-			payload->get_type(payload) == NOTIFY_V1)
+		if (payload->get_type(payload) == PLV2_NOTIFY ||
+			payload->get_type(payload) == PLV1_NOTIFY)
 		{
 			notify = (notify_payload_t*)payload;
 			if (notify->get_notify_type(notify) == type)
@@ -1212,8 +1212,8 @@ static char* get_string(private_message_t *this, char *buf, int len)
 		}
 		pos += written;
 		len -= written;
-		if (payload->get_type(payload) == NOTIFY ||
-			payload->get_type(payload) == NOTIFY_V1)
+		if (payload->get_type(payload) == PLV2_NOTIFY ||
+			payload->get_type(payload) == PLV1_NOTIFY)
 		{
 			notify_payload_t *notify;
 			notify_type_t type;
@@ -1239,7 +1239,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
 			pos += written;
 			len -= written;
 		}
-		if (payload->get_type(payload) == EXTENSIBLE_AUTHENTICATION)
+		if (payload->get_type(payload) == PLV2_EAP)
 		{
 			eap_payload_t *eap = (eap_payload_t*)payload;
 			u_int32_t vendor;
@@ -1268,8 +1268,8 @@ static char* get_string(private_message_t *this, char *buf, int len)
 			pos += written;
 			len -= written;
 		}
-		if (payload->get_type(payload) == CONFIGURATION ||
-			payload->get_type(payload) == CONFIGURATION_V1)
+		if (payload->get_type(payload) == PLV2_CONFIGURATION ||
+			payload->get_type(payload) == PLV1_CONFIGURATION)
 		{
 			cp_payload_t *cp = (cp_payload_t*)payload;
 			enumerator_t *attributes;
@@ -1365,7 +1365,7 @@ static void order_payloads(private_message_t *this)
 				notify = (notify_payload_t*)payload;
 
 				/**... and check notify for type. */
-				if (order.type != NOTIFY || order.notify == 0 ||
+				if (order.type != PLV2_NOTIFY || order.notify == 0 ||
 					order.notify == notify->get_notify_type(notify))
 				{
 					list->remove_at(list, enumerator);
@@ -1410,11 +1410,11 @@ static encryption_payload_t* wrap_payloads(private_message_t *this)
 
 	if (this->is_encrypted)
 	{
-		encryption = encryption_payload_create(ENCRYPTED_V1);
+		encryption = encryption_payload_create(PLV1_ENCRYPTED);
 	}
 	else
 	{
-		encryption = encryption_payload_create(ENCRYPTED);
+		encryption = encryption_payload_create(PLV2_ENCRYPTED);
 	}
 	while (payloads->remove_first(payloads, (void**)&current) == SUCCESS)
 	{
@@ -1500,7 +1500,7 @@ METHOD(message_t, generate, status_t,
 		{	/* insert a HASH payload as first payload */
 			hash_payload_t *hash_payload;
 
-			hash_payload = hash_payload_create(HASH_V1);
+			hash_payload = hash_payload_create(PLV1_HASH);
 			hash_payload->set_hash(hash_payload, hash);
 			this->payloads->insert_first(this->payloads, hash_payload);
 			if (this->exchange_type == INFORMATIONAL_V1)
@@ -1598,7 +1598,7 @@ METHOD(message_t, generate, status_t,
 	}
 	else
 	{
-		next_type = encryption ? ENCRYPTED : NO_PAYLOAD;
+		next_type = encryption ? PLV2_ENCRYPTED : PL_NONE;
 	}
 	payload->set_next_type(payload, next_type);
 	generator->generate_payload(generator, payload);
@@ -1683,7 +1683,7 @@ METHOD(message_t, parse_header, status_t,
 	DBG2(DBG_ENC, "parsing header of message");
 
 	this->parser->reset_context(this->parser);
-	status = this->parser->parse_payload(this->parser, HEADER,
+	status = this->parser->parse_payload(this->parser, PL_HEADER,
 										 (payload_t**)&ike_header);
 	if (status != SUCCESS)
 	{
@@ -1722,7 +1722,7 @@ METHOD(message_t, parse_header, status_t,
 	}
 	this->first_payload = ike_header->payload_interface.get_next_type(
 												&ike_header->payload_interface);
-	if (this->first_payload == FRAGMENT_V1 && this->is_encrypted)
+	if (this->first_payload == PLV1_FRAGMENT && this->is_encrypted)
 	{	/* racoon sets the encryted bit when sending a fragment, but these
 		 * messages are really not encrypted */
 		this->is_encrypted = FALSE;
@@ -1752,7 +1752,7 @@ static bool is_connectivity_check(private_message_t *this, payload_t *payload)
 {
 #ifdef ME
 	if (this->exchange_type == INFORMATIONAL &&
-		payload->get_type(payload) == NOTIFY)
+		payload->get_type(payload) == PLV2_NOTIFY)
 	{
 		notify_payload_t *notify = (notify_payload_t*)payload;
 
@@ -1784,7 +1784,7 @@ static status_t parse_payloads(private_message_t *this)
 		 * payload which is then handled just like a regular payload */
 		encryption_payload_t *encryption;
 
-		status = this->parser->parse_payload(this->parser, ENCRYPTED_V1,
+		status = this->parser->parse_payload(this->parser, PLV1_ENCRYPTED,
 											 (payload_t**)&encryption);
 		if (status != SUCCESS)
 		{
@@ -1797,7 +1797,7 @@ static status_t parse_payloads(private_message_t *this)
 		return SUCCESS;
 	}
 
-	while (type != NO_PAYLOAD)
+	while (type != PL_NONE)
 	{
 		DBG2(DBG_ENC, "starting parsing a %N payload",
 			 payload_type_names, type);
@@ -1826,7 +1826,7 @@ static status_t parse_payloads(private_message_t *this)
 
 		/* an encrypted payload is the last one, so STOP here. decryption is
 		 * done later */
-		if (type == ENCRYPTED)
+		if (type == PLV2_ENCRYPTED)
 		{
 			DBG2(DBG_ENC, "%N payload found, stop parsing",
 				 payload_type_names, type);
@@ -1923,6 +1923,24 @@ static status_t decrypt_and_extract(private_message_t *this, keymat_t *keymat,
 }
 
 /**
+ * Do we accept unencrypted ID/HASH payloads in Main Mode, as seen from
+ * some SonicWall boxes?
+ */
+static bool accept_unencrypted_mm(private_message_t *this, payload_type_t type)
+{
+	if (this->exchange_type == ID_PROT)
+	{
+		if (type == PLV1_ID || type == PLV1_HASH)
+		{
+			return lib->settings->get_bool(lib->settings,
+									"%s.accept_unencrypted_mainmode_messages",
+									FALSE, lib->ns);
+		}
+	}
+	return FALSE;
+}
+
+/**
  * Decrypt payload from the encryption payload
  */
 static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
@@ -1941,7 +1959,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
 
 		DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type);
 
-		if (type == ENCRYPTED || type == ENCRYPTED_V1)
+		if (type == PLV2_ENCRYPTED || type == PLV1_ENCRYPTED)
 		{
 			encryption_payload_t *encryption;
 
@@ -1978,7 +1996,8 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
 			this->exchange_type != AGGRESSIVE)
 		{
 			rule = get_payload_rule(this, type);
-			if (!rule || rule->encrypted)
+			if ((!rule || rule->encrypted) &&
+				!accept_unencrypted_mm(this, type))
 			{
 				DBG1(DBG_ENC, "payload type %N was not encrypted",
 					 payload_type_names, type);
@@ -2097,7 +2116,7 @@ METHOD(message_t, parse_body, status_t,
 			hash_payload_t *hash_payload;
 			chunk_t other_hash;
 
-			if (this->first_payload != HASH_V1)
+			if (this->first_payload != PLV1_HASH)
 			{
 				if (this->exchange_type == INFORMATIONAL_V1)
 				{
@@ -2111,7 +2130,7 @@ METHOD(message_t, parse_body, status_t,
 				chunk_free(&hash);
 				return VERIFY_ERROR;
 			}
-			hash_payload = (hash_payload_t*)get_payload(this, HASH_V1);
+			hash_payload = (hash_payload_t*)get_payload(this, PLV1_HASH);
 			other_hash = hash_payload->get_hash(hash_payload);
 			DBG3(DBG_ENC, "HASH received %B\nHASH expected %B",
 				 &other_hash, &hash);
@@ -2192,7 +2211,7 @@ message_t *message_create_from_packet(packet_t *packet)
 		},
 		.exchange_type = EXCHANGE_TYPE_UNDEFINED,
 		.is_request = TRUE,
-		.first_payload = NO_PAYLOAD,
+		.first_payload = PL_NONE,
 		.packet = packet,
 		.payloads = linked_list_create(),
 		.parser = parser_create(packet->get_data(packet)),
diff --git a/src/libcharon/encoding/parser.c b/src/libcharon/encoding/parser.c
index 9e7f831..c33e30d 100644
--- a/src/libcharon/encoding/parser.c
+++ b/src/libcharon/encoding/parser.c
@@ -15,7 +15,6 @@
  */
 
 #include <stdlib.h>
-#include <arpa/inet.h>
 #include <string.h>
 
 #include "parser.h"
@@ -486,15 +485,15 @@ METHOD(parser_t, parse_payload, status_t,
 				}
 				break;
 			}
-			case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE:
-			case PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1:
-			case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE:
-			case PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1:
-			case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE:
-			case PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1:
-			case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE:
-			case PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1:
-			case PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE:
+			case PAYLOAD_LIST + PLV2_TRANSFORM_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV1_TRANSFORM_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV2_CONFIGURATION_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV1_CONFIGURATION_ATTRIBUTE:
+			case PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE:
 			{
 				if (payload_length < header_length ||
 					!parse_list(this, rule_number, output + rule->offset,
diff --git a/src/libcharon/encoding/payloads/auth_payload.c b/src/libcharon/encoding/payloads/auth_payload.c
index 2410a1a..ee3ed54 100644
--- a/src/libcharon/encoding/payloads/auth_payload.c
+++ b/src/libcharon/encoding/payloads/auth_payload.c
@@ -135,7 +135,7 @@ METHOD(payload_t, get_header_length, int,
 METHOD(payload_t, get_type, payload_type_t,
 	private_auth_payload_t *this)
 {
-	return AUTHENTICATION;
+	return PLV2_AUTH;
 }
 
 METHOD(payload_t, get_next_type, payload_type_t,
@@ -214,7 +214,7 @@ auth_payload_t *auth_payload_create()
 			.get_data = _get_data,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 	);
 	return &this->public;
diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c
index 05d4105..43993ae 100644
--- a/src/libcharon/encoding/payloads/cert_payload.c
+++ b/src/libcharon/encoding/payloads/cert_payload.c
@@ -315,7 +315,7 @@ cert_payload_t *cert_payload_create(payload_type_t type)
 			.get_url = _get_url,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.type = type,
 	);
@@ -363,7 +363,7 @@ cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url)
 {
 	private_cert_payload_t *this;
 
-	this = (private_cert_payload_t*)cert_payload_create(CERTIFICATE);
+	this = (private_cert_payload_t*)cert_payload_create(PLV2_CERTIFICATE);
 	this->encoding = ENC_X509_HASH_AND_URL;
 	this->data = chunk_cat("cc", hash, chunk_create(url, strlen(url)));
 	this->payload_length = get_header_length(this) + this->data.len;
diff --git a/src/libcharon/encoding/payloads/certreq_payload.c b/src/libcharon/encoding/payloads/certreq_payload.c
index df5e73b..6ac90a2 100644
--- a/src/libcharon/encoding/payloads/certreq_payload.c
+++ b/src/libcharon/encoding/payloads/certreq_payload.c
@@ -66,7 +66,7 @@ struct private_certreq_payload_t {
 	chunk_t data;
 
 	/**
-	 * Payload type CERTIFICATE_REQUEST or CERTIFICATE_REQUEST_V1
+	 * Payload type PLV2_CERTREQ or PLV1_CERTREQ
 	 */
 	payload_type_t type;
 };
@@ -111,7 +111,7 @@ static encoding_rule_t encodings[] = {
 METHOD(payload_t, verify, status_t,
 	private_certreq_payload_t *this)
 {
-	if (this->type == CERTIFICATE_REQUEST &&
+	if (this->type == PLV2_CERTREQ &&
 		this->encoding == ENC_X509_SIGNATURE)
 	{
 		if (this->data.len % HASH_SIZE_SHA1)
@@ -218,7 +218,7 @@ METHOD(certreq_payload_t, create_keyid_enumerator, enumerator_t*,
 {
 	keyid_enumerator_t *enumerator;
 
-	if (this->type == CERTIFICATE_REQUEST_V1)
+	if (this->type == PLV1_CERTREQ)
 	{
 		return enumerator_create_empty();
 	}
@@ -276,7 +276,7 @@ certreq_payload_t *certreq_payload_create(payload_type_t type)
 			.destroy = _destroy,
 			.get_dn = _get_dn,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.type = type,
 	);
@@ -291,7 +291,7 @@ certreq_payload_t *certreq_payload_create_type(certificate_type_t type)
 	private_certreq_payload_t *this;
 
 	this = (private_certreq_payload_t*)
-					certreq_payload_create(CERTIFICATE_REQUEST);
+					certreq_payload_create(PLV2_CERTREQ);
 	switch (type)
 	{
 		case CERT_X509:
@@ -314,7 +314,7 @@ certreq_payload_t *certreq_payload_create_dn(identification_t *id)
 	private_certreq_payload_t *this;
 
 	this = (private_certreq_payload_t*)
-					certreq_payload_create(CERTIFICATE_REQUEST_V1);
+					certreq_payload_create(PLV1_CERTREQ);
 
 	this->encoding = ENC_X509_SIGNATURE;
 	this->data = chunk_clone(id->get_encoding(id));
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c
index 482eca8..481bb7b 100644
--- a/src/libcharon/encoding/payloads/configuration_attribute.c
+++ b/src/libcharon/encoding/payloads/configuration_attribute.c
@@ -61,7 +61,7 @@ struct private_configuration_attribute_t {
 	chunk_t value;
 
 	/**
-	 * Payload type, CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
+	 * Payload type, PLV2_CONFIGURATION_ATTRIBUTE or DATA_ATTRIBUTE_V1
 	 */
 	payload_type_t type;
 };
@@ -209,7 +209,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_configuration_attribute_t *this, encoding_rule_t **rules)
 {
-	if (this->type == CONFIGURATION_ATTRIBUTE)
+	if (this->type == PLV2_CONFIGURATION_ATTRIBUTE)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -233,7 +233,7 @@ METHOD(payload_t, get_type, payload_type_t,
 METHOD(payload_t, get_next_type, payload_type_t,
 	private_configuration_attribute_t *this)
 {
-	return NO_PAYLOAD;
+	return PL_NONE;
 }
 
 METHOD(payload_t, set_next_type, void,
@@ -335,7 +335,7 @@ configuration_attribute_t *configuration_attribute_create_value(
 	private_configuration_attribute_t *this;
 
 	this = (private_configuration_attribute_t*)
-					configuration_attribute_create(CONFIGURATION_ATTRIBUTE_V1);
+					configuration_attribute_create(PLV1_CONFIGURATION_ATTRIBUTE);
 	this->attr_type = ((u_int16_t)attr_type) & 0x7FFF;
 	this->length_or_value = value;
 	this->af_flag = TRUE;
diff --git a/src/libcharon/encoding/payloads/configuration_attribute.h b/src/libcharon/encoding/payloads/configuration_attribute.h
index ecc0f9c..946c1b5 100644
--- a/src/libcharon/encoding/payloads/configuration_attribute.h
+++ b/src/libcharon/encoding/payloads/configuration_attribute.h
@@ -68,7 +68,7 @@ struct configuration_attribute_t {
 /**
  * Creates an empty configuration attribute.
  *
- * @param type		CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
+ * @param type		PLV2_CONFIGURATION_ATTRIBUTE or PLV1_CONFIGURATION_ATTRIBUTE
  * @return			created configuration attribute
  */
 configuration_attribute_t *configuration_attribute_create(payload_type_t type);
@@ -76,7 +76,7 @@ configuration_attribute_t *configuration_attribute_create(payload_type_t type);
 /**
  * Creates a configuration attribute with type and value.
  *
- * @param type		CONFIGURATION_ATTRIBUTE or CONFIGURATION_ATTRIBUTE_V1
+ * @param type		PLV2_CONFIGURATION_ATTRIBUTE or PLV1_CONFIGURATION_ATTRIBUTE
  * @param attr_type	type of configuration attribute
  * @param chunk		attribute value, gets cloned
  * @return			created configuration attribute
@@ -89,7 +89,7 @@ configuration_attribute_t *configuration_attribute_create_chunk(
  *
  * @param attr_type	type of configuration attribute
  * @param value		attribute value, gets cloned
- * @return			created CONFIGURATION_ATTRIBUTE_V1 configuration attribute
+ * @return			created PLV1_CONFIGURATION_ATTRIBUTE configuration attribute
  */
 configuration_attribute_t *configuration_attribute_create_value(
 					configuration_attribute_type_t attr_type, u_int16_t value);
diff --git a/src/libcharon/encoding/payloads/cp_payload.c b/src/libcharon/encoding/payloads/cp_payload.c
index f6f373f..ef9df84 100644
--- a/src/libcharon/encoding/payloads/cp_payload.c
+++ b/src/libcharon/encoding/payloads/cp_payload.c
@@ -82,7 +82,7 @@ struct private_cp_payload_t {
 	u_int8_t cfg_type;
 
 	/**
-	 * CONFIGURATION or CONFIGURATION_V1
+	 * PLV2_CONFIGURATION or PLV1_CONFIGURATION
 	 */
 	payload_type_t type;
 };
@@ -111,7 +111,7 @@ static encoding_rule_t encodings_v2[] = {
 	{ RESERVED_BYTE,	offsetof(private_cp_payload_t, reserved_byte[1])},
 	{ RESERVED_BYTE,	offsetof(private_cp_payload_t, reserved_byte[2])},
 	/* list of configuration attributes in a list */
-	{ PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE,
+	{ PAYLOAD_LIST + PLV2_CONFIGURATION_ATTRIBUTE,
 						offsetof(private_cp_payload_t, attributes)		},
 };
 
@@ -152,7 +152,7 @@ static encoding_rule_t encodings_v1[] = {
 	{ RESERVED_BYTE,	offsetof(private_cp_payload_t, reserved_byte[0])},
 	{ U_INT_16,			offsetof(private_cp_payload_t, identifier)},
 	/* list of configuration attributes in a list */
-	{ PAYLOAD_LIST + CONFIGURATION_ATTRIBUTE_V1,
+	{ PAYLOAD_LIST + PLV1_CONFIGURATION_ATTRIBUTE,
 						offsetof(private_cp_payload_t, attributes)		},
 };
 
@@ -193,7 +193,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_cp_payload_t *this, encoding_rule_t **rules)
 {
-	if (this->type == CONFIGURATION)
+	if (this->type == PLV2_CONFIGURATION)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -314,7 +314,7 @@ cp_payload_t *cp_payload_create_type(payload_type_t type, config_type_t cfg_type
 			.set_identifier = _set_identifier,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.attributes = linked_list_create(),
 		.cfg_type = cfg_type,
diff --git a/src/libcharon/encoding/payloads/cp_payload.h b/src/libcharon/encoding/payloads/cp_payload.h
index c23bc0b..d466989 100644
--- a/src/libcharon/encoding/payloads/cp_payload.h
+++ b/src/libcharon/encoding/payloads/cp_payload.h
@@ -100,7 +100,7 @@ struct cp_payload_t {
 /**
  * Creates an empty configuration payload
  *
- * @param type		payload type, CONFIGURATION or CONFIGURATION_V1
+ * @param type		payload type, PLV2_CONFIGURATION or PLV1_CONFIGURATION
  * @return			empty configuration payload
  */
 cp_payload_t *cp_payload_create(payload_type_t type);
@@ -108,7 +108,7 @@ cp_payload_t *cp_payload_create(payload_type_t type);
 /**
  * Creates an cp_payload_t with type and value
  *
- * @param type		payload type, CONFIGURATION or CONFIGURATION_V1
+ * @param type		payload type, PLV2_CONFIGURATION or PLV1_CONFIGURATION
  * @param cfg_type	type of configuration payload to create
  * @return			created configuration payload
  */
diff --git a/src/libcharon/encoding/payloads/delete_payload.c b/src/libcharon/encoding/payloads/delete_payload.c
index 007411f..c2ab3b9 100644
--- a/src/libcharon/encoding/payloads/delete_payload.c
+++ b/src/libcharon/encoding/payloads/delete_payload.c
@@ -78,7 +78,7 @@ struct private_delete_payload_t {
 	chunk_t spis;
 
 	/**
-	 * Payload type, DELETE or DELETE_V1
+	 * Payload type, PLV2_DELETE or PLV1_DELETE
 	 */
 	payload_type_t type;
 };
@@ -178,7 +178,7 @@ METHOD(payload_t, verify, status_t,
 			break;
 		case PROTO_IKE:
 		case 0:
-			if (this->type == DELETE)
+			if (this->type == PLV2_DELETE)
 			{	/* IKEv2 deletion has no spi assigned! */
 				if (this->spi_size != 0)
 				{
@@ -206,7 +206,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_delete_payload_t *this, encoding_rule_t **rules)
 {
-	if (this->type == DELETE)
+	if (this->type == PLV2_DELETE)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -218,7 +218,7 @@ METHOD(payload_t, get_encoding_rules, int,
 METHOD(payload_t, get_header_length, int,
 	private_delete_payload_t *this)
 {
-	if (this->type == DELETE)
+	if (this->type == PLV2_DELETE)
 	{
 		return 8;
 	}
@@ -355,7 +355,7 @@ delete_payload_t *delete_payload_create(payload_type_t type,
 			.create_spi_enumerator = _create_spi_enumerator,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.protocol_id = protocol_id,
 		.doi = IKEV1_DOI_IPSEC,
 		.type = type,
@@ -364,7 +364,7 @@ delete_payload_t *delete_payload_create(payload_type_t type,
 
 	if (protocol_id == PROTO_IKE)
 	{
-		if (type == DELETE_V1)
+		if (type == PLV1_DELETE)
 		{
 			this->spi_size = 16;
 		}
diff --git a/src/libcharon/encoding/payloads/delete_payload.h b/src/libcharon/encoding/payloads/delete_payload.h
index afce1ec..46a89ea 100644
--- a/src/libcharon/encoding/payloads/delete_payload.h
+++ b/src/libcharon/encoding/payloads/delete_payload.h
@@ -76,7 +76,7 @@ struct delete_payload_t {
 /**
  * Creates an empty delete_payload_t object.
  *
- * @param type			DELETE or DELETE_V1
+ * @param type			PLV2_DELETE or PLV1_DELETE
  * @param protocol_id	protocol, such as AH|ESP
  * @return 				delete_payload_t object
  */
diff --git a/src/libcharon/encoding/payloads/eap_payload.c b/src/libcharon/encoding/payloads/eap_payload.c
index f2f35aa..ebdf8a3 100644
--- a/src/libcharon/encoding/payloads/eap_payload.c
+++ b/src/libcharon/encoding/payloads/eap_payload.c
@@ -162,7 +162,7 @@ METHOD(payload_t, get_header_length, int,
 METHOD(payload_t, get_payload_type, payload_type_t,
 	private_eap_payload_t *this)
 {
-	return EXTENSIBLE_AUTHENTICATION;
+	return PLV2_EAP;
 }
 
 METHOD(payload_t, get_next_type, payload_type_t,
@@ -341,7 +341,7 @@ eap_payload_t *eap_payload_create()
 			.is_expanded = _is_expanded,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 	);
 	return &this->public;
diff --git a/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c
index 6a9f9c3..5784562 100644
--- a/src/libcharon/encoding/payloads/encryption_payload.c
+++ b/src/libcharon/encoding/payloads/encryption_payload.c
@@ -74,7 +74,7 @@ struct private_encryption_payload_t {
 	linked_list_t *payloads;
 
 	/**
-	 * Type of payload, ENCRYPTED or ENCRYPTED_V1
+	 * Type of payload, PLV2_ENCRYPTED or PLV1_ENCRYPTED
 	 */
 	payload_type_t type;
 };
@@ -145,7 +145,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_encryption_payload_t *this, encoding_rule_t **rules)
 {
-	if (this->type == ENCRYPTED)
+	if (this->type == PLV2_ENCRYPTED)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -157,7 +157,7 @@ METHOD(payload_t, get_encoding_rules, int,
 METHOD(payload_t, get_header_length, int,
 	private_encryption_payload_t *this)
 {
-	if (this->type == ENCRYPTED)
+	if (this->type == PLV2_ENCRYPTED)
 	{
 		return 4;
 	}
@@ -241,7 +241,7 @@ METHOD(encryption_payload_t, add_payload, void,
 	{
 		this->next_payload = payload->get_type(payload);
 	}
-	payload->set_next_type(payload, NO_PAYLOAD);
+	payload->set_next_type(payload, PL_NONE);
 	this->payloads->insert_last(this->payloads, payload);
 	compute_length(this);
 }
@@ -281,7 +281,7 @@ static chunk_t generate(private_encryption_payload_t *this,
 			generator->generate_payload(generator, current);
 			current = next;
 		}
-		current->set_next_type(current, NO_PAYLOAD);
+		current->set_next_type(current, PL_NONE);
 		generator->generate_payload(generator, current);
 
 		chunk = generator->get_chunk(generator, &lenpos);
@@ -447,7 +447,7 @@ static status_t parse(private_encryption_payload_t *this, chunk_t plain)
 
 	parser = parser_create(plain);
 	type = this->next_payload;
-	while (type != NO_PAYLOAD)
+	while (type != PL_NONE)
 	{
 		payload_t *payload;
 
@@ -618,13 +618,13 @@ encryption_payload_t *encryption_payload_create(payload_type_t type)
 			.decrypt = _decrypt,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payloads = linked_list_create(),
 		.type = type,
 	);
 	this->payload_length = get_header_length(this);
 
-	if (type == ENCRYPTED_V1)
+	if (type == PLV1_ENCRYPTED)
 	{
 		this->public.encrypt = _encrypt_v1;
 		this->public.decrypt = _decrypt_v1;
diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encryption_payload.h
index f4fc7d6..ee44c2d 100644
--- a/src/libcharon/encoding/payloads/encryption_payload.h
+++ b/src/libcharon/encoding/payloads/encryption_payload.h
@@ -103,7 +103,7 @@ struct encryption_payload_t {
 /**
  * Creates an empty encryption_payload_t object.
  *
- * @param type		ENCRYPTED or ENCRYPTED_V1
+ * @param type		PLV2_ENCRYPTED or PLV1_ENCRYPTED
  * @return			encryption_payload_t object
  */
 encryption_payload_t *encryption_payload_create(payload_type_t type);
diff --git a/src/libcharon/encoding/payloads/endpoint_notify.c b/src/libcharon/encoding/payloads/endpoint_notify.c
index 25fb42a..ebe5f32 100644
--- a/src/libcharon/encoding/payloads/endpoint_notify.c
+++ b/src/libcharon/encoding/payloads/endpoint_notify.c
@@ -227,7 +227,7 @@ METHOD(endpoint_notify_t, build_notify, notify_payload_t*,
 	chunk_t data;
 	notify_payload_t *notify;
 
-	notify = notify_payload_create(NOTIFY);
+	notify = notify_payload_create(PLV2_NOTIFY);
 	notify->set_notify_type(notify, ME_ENDPOINT);
 	data = build_notification_data(this);
 	notify->set_notification_data(notify, data);
diff --git a/src/libcharon/encoding/payloads/fragment_payload.c b/src/libcharon/encoding/payloads/fragment_payload.c
index 1a6b323..b861fcc 100644
--- a/src/libcharon/encoding/payloads/fragment_payload.c
+++ b/src/libcharon/encoding/payloads/fragment_payload.c
@@ -124,7 +124,7 @@ METHOD(payload_t, get_header_length, int,
 METHOD(payload_t, get_type, payload_type_t,
 	private_fragment_payload_t *this)
 {
-	return FRAGMENT_V1;
+	return PLV1_FRAGMENT;
 }
 
 METHOD(payload_t, get_next_type, payload_type_t,
@@ -201,7 +201,7 @@ fragment_payload_t *fragment_payload_create()
 			.get_data = _get_data,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 	);
 	this->payload_length = get_header_length(this);
 	return &this->public;
diff --git a/src/libcharon/encoding/payloads/hash_payload.c b/src/libcharon/encoding/payloads/hash_payload.c
index 0cf63ba..a12b018 100644
--- a/src/libcharon/encoding/payloads/hash_payload.c
+++ b/src/libcharon/encoding/payloads/hash_payload.c
@@ -52,7 +52,7 @@ struct private_hash_payload_t {
 	chunk_t hash;
 
 	/**
-	 * either HASH_V1 or NAT_D_V1
+	 * either PLV1_HASH or PLV1_NAT_D
 	 */
 	payload_type_t type;
 };
@@ -169,7 +169,7 @@ hash_payload_t *hash_payload_create(payload_type_t type)
 			.get_hash = _get_hash,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.type = type,
 	);
diff --git a/src/libcharon/encoding/payloads/hash_payload.h b/src/libcharon/encoding/payloads/hash_payload.h
index cfe2846..604de48 100644
--- a/src/libcharon/encoding/payloads/hash_payload.h
+++ b/src/libcharon/encoding/payloads/hash_payload.h
@@ -59,7 +59,7 @@ struct hash_payload_t {
 /**
  * Creates an empty hash_payload_t object.
  *
- * @param type		either HASH_V1 or NAT_D_V1
+ * @param type		either PLV1_HASH or PLV1_NAT_D
  * @return			hash_payload_t object
  */
 hash_payload_t *hash_payload_create(payload_type_t type);
diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c
index 7470bb3..a002a8f 100644
--- a/src/libcharon/encoding/payloads/id_payload.c
+++ b/src/libcharon/encoding/payloads/id_payload.c
@@ -81,7 +81,7 @@ struct private_id_payload_t {
 	u_int16_t port;
 
 	/**
-	 * one of ID_INITIATOR, ID_RESPONDER, IDv1 and NAT_OA_V1
+	 * one of PLV2_ID_INITIATOR, PLV2_ID_RESPONDER, IDv1 and PLV1_NAT_OA
 	 */
 	payload_type_t type;
 };
@@ -165,7 +165,7 @@ METHOD(payload_t, verify, status_t,
 {
 	bool bad_length = FALSE;
 
-	if ((this->type == NAT_OA_V1 || this->type == NAT_OA_DRAFT_00_03_V1) &&
+	if ((this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03) &&
 		this->id_type != ID_IPV4_ADDR && this->id_type != ID_IPV6_ADDR)
 	{
 		DBG1(DBG_ENC, "invalid ID type %N for %N payload", id_type_names,
@@ -195,8 +195,8 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_id_payload_t *this, encoding_rule_t **rules)
 {
-	if (this->type == ID_V1 ||
-		this->type == NAT_OA_V1 || this->type == NAT_OA_DRAFT_00_03_V1)
+	if (this->type == PLV1_ID ||
+		this->type == PLV1_NAT_OA || this->type == PLV1_NAT_OA_DRAFT_00_03)
 	{
 		*rules = encodings_v1;
 		return countof(encodings_v1);
@@ -368,7 +368,7 @@ id_payload_t *id_payload_create(payload_type_t type)
 			.get_ts = _get_ts,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.type = type,
 	);
@@ -400,7 +400,7 @@ id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts)
 	u_int8_t mask;
 	host_t *net;
 
-	this = (private_id_payload_t*)id_payload_create(ID_V1);
+	this = (private_id_payload_t*)id_payload_create(PLV1_ID);
 
 	if (ts->is_host(ts, NULL))
 	{
diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h
index 9a62494..df1d075 100644
--- a/src/libcharon/encoding/payloads/id_payload.h
+++ b/src/libcharon/encoding/payloads/id_payload.h
@@ -70,7 +70,7 @@ struct id_payload_t {
 /**
  * Creates an empty id_payload_t object.
  *
- * @param type		one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
+ * @param type		one of PLV2_ID_INITIATOR, PLV2_ID_RESPONDER, PLV1_ID and PLV1_NAT_OA
  * @return			id_payload_t object
  */
 id_payload_t *id_payload_create(payload_type_t type);
@@ -78,7 +78,7 @@ id_payload_t *id_payload_create(payload_type_t type);
 /**
  * Creates an id_payload_t from an existing identification_t object.
  *
- * @param type		one of ID_INITIATOR, ID_RESPONDER, ID_V1 and NAT_OA_V1
+ * @param type		one of PLV2_ID_INITIATOR, PLV2_ID_RESPONDER, PLV1_ID and PLV1_NAT_OA
  * @param id		identification_t object
  * @return			id_payload_t object
  */
@@ -89,7 +89,7 @@ id_payload_t *id_payload_create_from_identification(payload_type_t type,
  * Create an IKEv1 ID_ADDR_SUBNET/RANGE identity from a traffic selector.
  *
  * @param ts		traffic selector
- * @return			ID_V1 id_paylad_t object.
+ * @return			PLV1_ID id_paylad_t object.
  */
 id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts);
 
diff --git a/src/libcharon/encoding/payloads/ike_header.c b/src/libcharon/encoding/payloads/ike_header.c
index 58b6241..7015667 100644
--- a/src/libcharon/encoding/payloads/ike_header.c
+++ b/src/libcharon/encoding/payloads/ike_header.c
@@ -262,7 +262,7 @@ METHOD(payload_t, get_header_length, int,
 METHOD(payload_t, get_type, payload_type_t,
 	private_ike_header_t *this)
 {
-	return HEADER;
+	return PL_HEADER;
 }
 
 METHOD(payload_t, get_next_type, payload_type_t,
diff --git a/src/libcharon/encoding/payloads/ke_payload.c b/src/libcharon/encoding/payloads/ke_payload.c
index 438ea46..4f552d6 100644
--- a/src/libcharon/encoding/payloads/ke_payload.c
+++ b/src/libcharon/encoding/payloads/ke_payload.c
@@ -69,7 +69,7 @@ struct private_ke_payload_t {
 	chunk_t key_exchange_data;
 
 	/**
-	 * Payload type, KEY_EXCHANGE or KEY_EXCHANGE_V1
+	 * Payload type, PLV2_KEY_EXCHANGE or PLV1_KEY_EXCHANGE
 	 */
 	payload_type_t type;
 };
@@ -148,7 +148,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_ke_payload_t *this, encoding_rule_t **rules)
 {
-	if (this->type == KEY_EXCHANGE)
+	if (this->type == PLV2_KEY_EXCHANGE)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -160,7 +160,7 @@ METHOD(payload_t, get_encoding_rules, int,
 METHOD(payload_t, get_header_length, int,
 	private_ke_payload_t *this)
 {
-	if (this->type == KEY_EXCHANGE)
+	if (this->type == PLV2_KEY_EXCHANGE)
 	{
 		return 8;
 	}
@@ -233,7 +233,7 @@ ke_payload_t *ke_payload_create(payload_type_t type)
 			.get_dh_group_number = _get_dh_group_number,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.dh_group_number = MODP_NONE,
 		.type = type,
 	);
diff --git a/src/libcharon/encoding/payloads/ke_payload.h b/src/libcharon/encoding/payloads/ke_payload.h
index d3aa184..dfc6308 100644
--- a/src/libcharon/encoding/payloads/ke_payload.h
+++ b/src/libcharon/encoding/payloads/ke_payload.h
@@ -63,7 +63,7 @@ struct ke_payload_t {
 /**
  * Creates an empty ke_payload_t object.
  *
- * @param type		KEY_EXCHANGE or KEY_EXCHANGE_V1
+ * @param type		PLV2_KEY_EXCHANGE or PLV1_KEY_EXCHANGE
  * @return			ke_payload_t object
  */
 ke_payload_t *ke_payload_create(payload_type_t type);
@@ -71,7 +71,7 @@ ke_payload_t *ke_payload_create(payload_type_t type);
 /**
  * Creates a ke_payload_t from a diffie_hellman_t.
  *
- * @param type		KEY_EXCHANGE or KEY_EXCHANGE_V1
+ * @param type		PLV2_KEY_EXCHANGE or PLV1_KEY_EXCHANGE
  * @param dh		diffie hellman object containing group and key
  * @return 			ke_payload_t object
  */
diff --git a/src/libcharon/encoding/payloads/nonce_payload.c b/src/libcharon/encoding/payloads/nonce_payload.c
index 3c5eeb5..b0d1c60 100644
--- a/src/libcharon/encoding/payloads/nonce_payload.c
+++ b/src/libcharon/encoding/payloads/nonce_payload.c
@@ -60,7 +60,7 @@ struct private_nonce_payload_t {
 	chunk_t nonce;
 
 	/**
-	 * Payload type, NONCE or NONCE_V1
+	 * Payload type, PLV2_NONCE or PLV1_NONCE
 	 */
 	payload_type_t type;
 };
@@ -110,12 +110,12 @@ METHOD(payload_t, verify, status_t,
 	{
 		bad_length = TRUE;
 	}
-	if (this->type == NONCE &&
+	if (this->type == PLV2_NONCE &&
 		this->nonce.len < 16)
 	{
 		bad_length = TRUE;
 	}
-	if (this->type == NONCE_V1 &&
+	if (this->type == PLV1_NONCE &&
 		this->nonce.len < 8)
 	{
 		bad_length = TRUE;
@@ -209,7 +209,7 @@ nonce_payload_t *nonce_payload_create(payload_type_t type)
 			.get_nonce = _get_nonce,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.type = type,
 	);
diff --git a/src/libcharon/encoding/payloads/nonce_payload.h b/src/libcharon/encoding/payloads/nonce_payload.h
index 5c47f5f..ee8ad17 100644
--- a/src/libcharon/encoding/payloads/nonce_payload.h
+++ b/src/libcharon/encoding/payloads/nonce_payload.h
@@ -64,7 +64,7 @@ struct nonce_payload_t {
 /**
  * Creates an empty nonce_payload_t object
  *
- * @param type		NONCE or NONCE_V1
+ * @param type		PLV2_NONCE or PLV1_NONCE
  * @return			nonce_payload_t object
  */
 nonce_payload_t *nonce_payload_create(payload_type_t type);
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c
index 889ad63..dd92e42 100644
--- a/src/libcharon/encoding/payloads/notify_payload.c
+++ b/src/libcharon/encoding/payloads/notify_payload.c
@@ -302,7 +302,7 @@ struct private_notify_payload_t {
 	chunk_t notify_data;
 
 	/**
-	 * Type of payload, NOTIFY or NOTIFY_V1
+	 * Type of payload, PLV2_NOTIFY or PLV1_NOTIFY
 	 */
 	payload_type_t type;
 };
@@ -427,7 +427,7 @@ METHOD(payload_t, verify, status_t,
 	{
 		case INVALID_KE_PAYLOAD:
 		{
-			if (this->type == NOTIFY && this->notify_data.len != 2)
+			if (this->type == PLV2_NOTIFY && this->notify_data.len != 2)
 			{
 				bad_length = TRUE;
 			}
@@ -447,7 +447,7 @@ METHOD(payload_t, verify, status_t,
 		case INVALID_MAJOR_VERSION:
 		case NO_PROPOSAL_CHOSEN:
 		{
-			if (this->type == NOTIFY && this->notify_data.len != 0)
+			if (this->type == PLV2_NOTIFY && this->notify_data.len != 0)
 			{
 				bad_length = TRUE;
 			}
@@ -531,7 +531,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_notify_payload_t *this, encoding_rule_t **rules)
 {
-	if (this->type == NOTIFY)
+	if (this->type == PLV2_NOTIFY)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -543,7 +543,7 @@ METHOD(payload_t, get_encoding_rules, int,
 METHOD(payload_t, get_header_length, int,
 	private_notify_payload_t *this)
 {
-	if (this->type == NOTIFY)
+	if (this->type == PLV2_NOTIFY)
 	{
 		return 8 + this->spi_size;
 	}
@@ -726,7 +726,7 @@ notify_payload_t *notify_payload_create(payload_type_t type)
 			.destroy = _destroy,
 		},
 		.doi = IKEV1_DOI_IPSEC,
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.type = type,
 	);
 	compute_length(this);
diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h
index c67644a..3c56f06 100644
--- a/src/libcharon/encoding/payloads/notify_payload.h
+++ b/src/libcharon/encoding/payloads/notify_payload.h
@@ -281,7 +281,7 @@ struct notify_payload_t {
 /**
  * Creates an empty notify_payload_t object
  *
- * @param type		payload type, NOTIFY or NOTIFY_V1
+ * @param type		payload type, PLV2_NOTIFY or PLV1_NOTIFY
  * @return			created notify_payload_t object
  */
 notify_payload_t *notify_payload_create(payload_type_t type);
@@ -289,7 +289,7 @@ notify_payload_t *notify_payload_create(payload_type_t type);
 /**
  * Creates an notify_payload_t object of specific type for specific protocol id.
  *
- * @param type					payload type, NOTIFY or NOTIFY_V1
+ * @param type					payload type, PLV2_NOTIFY or PLV1_NOTIFY
  * @param protocol				protocol id (IKE, AH or ESP)
  * @param notify				type of notify
  * @return						notify_payload_t object
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index f9dd33e..fd61662 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -39,16 +39,16 @@
 #include <encoding/payloads/fragment_payload.h>
 #include <encoding/payloads/unknown_payload.h>
 
-ENUM_BEGIN(payload_type_names, NO_PAYLOAD, NO_PAYLOAD,
-	"NO_PAYLOAD");
-ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
+ENUM_BEGIN(payload_type_names, PL_NONE, PL_NONE,
+	"PL_NONE");
+ENUM_NEXT(payload_type_names, PLV1_SECURITY_ASSOCIATION, PLV1_CONFIGURATION, PL_NONE,
 	"SECURITY_ASSOCIATION_V1",
 	"PROPOSAL_V1",
 	"TRANSFORM_V1",
 	"KEY_EXCHANGE_V1",
 	"ID_V1",
 	"CERTIFICATE_V1",
-	"CERTIFICATE_REQUEST_V1",
+	"CERTREQ_V1",
 	"HASH_V1",
 	"SIGNATURE_V1",
 	"NONCE_V1",
@@ -56,41 +56,41 @@ ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYL
 	"DELETE_V1",
 	"VENDOR_ID_V1",
 	"CONFIGURATION_V1");
-ENUM_NEXT(payload_type_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
+ENUM_NEXT(payload_type_names, PLV1_NAT_D, PLV1_NAT_OA, PLV1_CONFIGURATION,
 	"NAT_D_V1",
 	"NAT_OA_V1");
-ENUM_NEXT(payload_type_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
+ENUM_NEXT(payload_type_names, PLV2_SECURITY_ASSOCIATION, PLV2_GSPM, PLV1_NAT_OA,
 	"SECURITY_ASSOCIATION",
 	"KEY_EXCHANGE",
 	"ID_INITIATOR",
 	"ID_RESPONDER",
 	"CERTIFICATE",
-	"CERTIFICATE_REQUEST",
-	"AUTHENTICATION",
+	"CERTREQ",
+	"AUTH",
 	"NONCE",
 	"NOTIFY",
 	"DELETE",
 	"VENDOR_ID",
-	"TRAFFIC_SELECTOR_INITIATOR",
-	"TRAFFIC_SELECTOR_RESPONDER",
+	"TS_INITIATOR",
+	"TS_RESPONDER",
 	"ENCRYPTED",
 	"CONFIGURATION",
-	"EXTENSIBLE_AUTHENTICATION",
-	"GENERIC_SECURE_PASSWORD_METHOD");
+	"EAP",
+	"GSPM");
 #ifdef ME
-ENUM_NEXT(payload_type_names, ID_PEER, ID_PEER, GENERIC_SECURE_PASSWORD_METHOD,
+ENUM_NEXT(payload_type_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_GSPM,
 	"ID_PEER");
-ENUM_NEXT(payload_type_names, NAT_D_DRAFT_00_03_V1, FRAGMENT_V1, ID_PEER,
+ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_ID_PEER,
 	"NAT_D_DRAFT_V1",
 	"NAT_OA_DRAFT_V1",
 	"FRAGMENT");
 #else
-ENUM_NEXT(payload_type_names, NAT_D_DRAFT_00_03_V1, FRAGMENT_V1, GENERIC_SECURE_PASSWORD_METHOD,
+ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_GSPM,
 	"NAT_D_DRAFT_V1",
 	"NAT_OA_DRAFT_V1",
 	"FRAGMENT");
 #endif /* ME */
-ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, FRAGMENT_V1,
+ENUM_NEXT(payload_type_names, PL_HEADER, PLV1_ENCRYPTED, PLV1_FRAGMENT,
 	"HEADER",
 	"PROPOSAL_SUBSTRUCTURE",
 	"PROPOSAL_SUBSTRUCTURE_V1",
@@ -102,12 +102,12 @@ ENUM_NEXT(payload_type_names, HEADER, ENCRYPTED_V1, FRAGMENT_V1,
 	"CONFIGURATION_ATTRIBUTE",
 	"CONFIGURATION_ATTRIBUTE_V1",
 	"ENCRYPTED_V1");
-ENUM_END(payload_type_names, ENCRYPTED_V1);
+ENUM_END(payload_type_names, PLV1_ENCRYPTED);
 
 /* short forms of payload names */
-ENUM_BEGIN(payload_type_short_names, NO_PAYLOAD, NO_PAYLOAD,
+ENUM_BEGIN(payload_type_short_names, PL_NONE, PL_NONE,
 	"--");
-ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, NO_PAYLOAD,
+ENUM_NEXT(payload_type_short_names, PLV1_SECURITY_ASSOCIATION, PLV1_CONFIGURATION, PL_NONE,
 	"SA",
 	"PROP",
 	"TRANS",
@@ -122,10 +122,10 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION_V1, CONFIGURATION_V1, N
 	"D",
 	"V",
 	"CP");
-ENUM_NEXT(payload_type_short_names, NAT_D_V1, NAT_OA_V1, CONFIGURATION_V1,
+ENUM_NEXT(payload_type_short_names, PLV1_NAT_D, PLV1_NAT_OA, PLV1_CONFIGURATION,
 	"NAT-D",
 	"NAT-OA");
-ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWORD_METHOD, NAT_OA_V1,
+ENUM_NEXT(payload_type_short_names, PLV2_SECURITY_ASSOCIATION, PLV2_GSPM, PLV1_NAT_OA,
 	"SA",
 	"KE",
 	"IDi",
@@ -144,19 +144,19 @@ ENUM_NEXT(payload_type_short_names, SECURITY_ASSOCIATION, GENERIC_SECURE_PASSWOR
 	"EAP",
 	"GSPM");
 #ifdef ME
-ENUM_NEXT(payload_type_short_names, ID_PEER, ID_PEER, GENERIC_SECURE_PASSWORD_METHOD,
+ENUM_NEXT(payload_type_short_names, PLV2_ID_PEER, PLV2_ID_PEER, PLV2_GSPM,
 	"IDp");
-ENUM_NEXT(payload_type_short_names, NAT_D_DRAFT_00_03_V1, FRAGMENT_V1, ID_PEER,
+ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_ID_PEER,
 	"NAT-D",
 	"NAT-OA",
 	"FRAG");
 #else
-ENUM_NEXT(payload_type_short_names, NAT_D_DRAFT_00_03_V1, FRAGMENT_V1, GENERIC_SECURE_PASSWORD_METHOD,
+ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_GSPM,
 	"NAT-D",
 	"NAT-OA",
 	"FRAG");
 #endif /* ME */
-ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, FRAGMENT_V1,
+ENUM_NEXT(payload_type_short_names, PL_HEADER, PLV1_ENCRYPTED, PLV1_FRAGMENT,
 	"HDR",
 	"PROP",
 	"PROP",
@@ -168,7 +168,7 @@ ENUM_NEXT(payload_type_short_names, HEADER, ENCRYPTED_V1, FRAGMENT_V1,
 	"CATTR",
 	"CATTR",
 	"E");
-ENUM_END(payload_type_short_names, ENCRYPTED_V1);
+ENUM_END(payload_type_short_names, PLV1_ENCRYPTED);
 
 /*
  * see header
@@ -177,75 +177,75 @@ payload_t *payload_create(payload_type_t type)
 {
 	switch (type)
 	{
-		case HEADER:
+		case PL_HEADER:
 			return (payload_t*)ike_header_create();
-		case SECURITY_ASSOCIATION:
-		case SECURITY_ASSOCIATION_V1:
+		case PLV2_SECURITY_ASSOCIATION:
+		case PLV1_SECURITY_ASSOCIATION:
 			return (payload_t*)sa_payload_create(type);
-		case PROPOSAL_SUBSTRUCTURE:
-		case PROPOSAL_SUBSTRUCTURE_V1:
+		case PLV2_PROPOSAL_SUBSTRUCTURE:
+		case PLV1_PROPOSAL_SUBSTRUCTURE:
 			return (payload_t*)proposal_substructure_create(type);
-		case TRANSFORM_SUBSTRUCTURE:
-		case TRANSFORM_SUBSTRUCTURE_V1:
+		case PLV2_TRANSFORM_SUBSTRUCTURE:
+		case PLV1_TRANSFORM_SUBSTRUCTURE:
 			return (payload_t*)transform_substructure_create(type);
-		case TRANSFORM_ATTRIBUTE:
-		case TRANSFORM_ATTRIBUTE_V1:
+		case PLV2_TRANSFORM_ATTRIBUTE:
+		case PLV1_TRANSFORM_ATTRIBUTE:
 			return (payload_t*)transform_attribute_create(type);
-		case NONCE:
-		case NONCE_V1:
+		case PLV2_NONCE:
+		case PLV1_NONCE:
 			return (payload_t*)nonce_payload_create(type);
-		case ID_INITIATOR:
-		case ID_RESPONDER:
-		case ID_V1:
-		case NAT_OA_V1:
-		case NAT_OA_DRAFT_00_03_V1:
+		case PLV2_ID_INITIATOR:
+		case PLV2_ID_RESPONDER:
+		case PLV1_ID:
+		case PLV1_NAT_OA:
+		case PLV1_NAT_OA_DRAFT_00_03:
 #ifdef ME
-		case ID_PEER:
+		case PLV2_ID_PEER:
 #endif /* ME */
 			return (payload_t*)id_payload_create(type);
-		case AUTHENTICATION:
+		case PLV2_AUTH:
 			return (payload_t*)auth_payload_create();
-		case CERTIFICATE:
-		case CERTIFICATE_V1:
+		case PLV2_CERTIFICATE:
+		case PLV1_CERTIFICATE:
 			return (payload_t*)cert_payload_create(type);
-		case CERTIFICATE_REQUEST:
-		case CERTIFICATE_REQUEST_V1:
+		case PLV2_CERTREQ:
+		case PLV1_CERTREQ:
 			return (payload_t*)certreq_payload_create(type);
-		case TRAFFIC_SELECTOR_SUBSTRUCTURE:
+		case PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE:
 			return (payload_t*)traffic_selector_substructure_create();
-		case TRAFFIC_SELECTOR_INITIATOR:
+		case PLV2_TS_INITIATOR:
 			return (payload_t*)ts_payload_create(TRUE);
-		case TRAFFIC_SELECTOR_RESPONDER:
+		case PLV2_TS_RESPONDER:
 			return (payload_t*)ts_payload_create(FALSE);
-		case KEY_EXCHANGE:
-		case KEY_EXCHANGE_V1:
+		case PLV2_KEY_EXCHANGE:
+		case PLV1_KEY_EXCHANGE:
 			return (payload_t*)ke_payload_create(type);
-		case NOTIFY:
-		case NOTIFY_V1:
+		case PLV2_NOTIFY:
+		case PLV1_NOTIFY:
 			return (payload_t*)notify_payload_create(type);
-		case DELETE:
-		case DELETE_V1:
+		case PLV2_DELETE:
+		case PLV1_DELETE:
 			return (payload_t*)delete_payload_create(type, 0);
-		case VENDOR_ID:
-		case VENDOR_ID_V1:
+		case PLV2_VENDOR_ID:
+		case PLV1_VENDOR_ID:
 			return (payload_t*)vendor_id_payload_create(type);
-		case HASH_V1:
-		case SIGNATURE_V1:
-		case NAT_D_V1:
-		case NAT_D_DRAFT_00_03_V1:
+		case PLV1_HASH:
+		case PLV1_SIGNATURE:
+		case PLV1_NAT_D:
+		case PLV1_NAT_D_DRAFT_00_03:
 			return (payload_t*)hash_payload_create(type);
-		case CONFIGURATION:
-		case CONFIGURATION_V1:
+		case PLV2_CONFIGURATION:
+		case PLV1_CONFIGURATION:
 			return (payload_t*)cp_payload_create(type);
-		case CONFIGURATION_ATTRIBUTE:
-		case CONFIGURATION_ATTRIBUTE_V1:
+		case PLV2_CONFIGURATION_ATTRIBUTE:
+		case PLV1_CONFIGURATION_ATTRIBUTE:
 			return (payload_t*)configuration_attribute_create(type);
-		case EXTENSIBLE_AUTHENTICATION:
+		case PLV2_EAP:
 			return (payload_t*)eap_payload_create();
-		case ENCRYPTED:
-		case ENCRYPTED_V1:
+		case PLV2_ENCRYPTED:
+		case PLV1_ENCRYPTED:
 			return (payload_t*)encryption_payload_create(type);
-		case FRAGMENT_V1:
+		case PLV1_FRAGMENT:
 			return (payload_t*)fragment_payload_create();
 		default:
 			return (payload_t*)unknown_payload_create(type);
@@ -257,29 +257,29 @@ payload_t *payload_create(payload_type_t type)
  */
 bool payload_is_known(payload_type_t type)
 {
-	if (type == HEADER)
+	if (type == PL_HEADER)
 	{
 		return TRUE;
 	}
-	if (type >= SECURITY_ASSOCIATION && type <= EXTENSIBLE_AUTHENTICATION)
+	if (type >= PLV2_SECURITY_ASSOCIATION && type <= PLV2_EAP)
 	{
 		return TRUE;
 	}
-	if (type >= SECURITY_ASSOCIATION_V1 && type <= CONFIGURATION_V1)
+	if (type >= PLV1_SECURITY_ASSOCIATION && type <= PLV1_CONFIGURATION)
 	{
 		return TRUE;
 	}
-	if (type >= NAT_D_V1 && type <= NAT_OA_V1)
+	if (type >= PLV1_NAT_D && type <= PLV1_NAT_OA)
 	{
 		return TRUE;
 	}
 #ifdef ME
-	if (type == ID_PEER)
+	if (type == PLV2_ID_PEER)
 	{
 		return TRUE;
 	}
 #endif
-	if (type >= NAT_D_DRAFT_00_03_V1 && type <= FRAGMENT_V1)
+	if (type >= PLV1_NAT_D_DRAFT_00_03 && type <= PLV1_FRAGMENT)
 	{
 		return TRUE;
 	}
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index 0e8a926..d9dd619 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -45,195 +45,195 @@ enum payload_type_t {
 	/**
 	 * End of payload list in next_payload
 	 */
-	NO_PAYLOAD = 0,
+	PL_NONE = 0,
 
 	/**
 	 * The security association (SA) payload containing proposals.
 	 */
-	SECURITY_ASSOCIATION_V1 = 1,
+	PLV1_SECURITY_ASSOCIATION = 1,
 
 	/**
 	 * The proposal payload, containing transforms.
 	 */
-	PROPOSAL_V1 = 2,
+	PLV1_PROPOSAL = 2,
 
 	/**
 	 * The transform payload.
 	 */
-	TRANSFORM_V1 = 3,
+	PLV1_TRANSFORM = 3,
 
 	/**
 	 * The key exchange (KE) payload containing diffie-hellman values.
 	 */
-	KEY_EXCHANGE_V1 = 4,
+	PLV1_KEY_EXCHANGE = 4,
 
 	/**
 	 * ID payload.
 	 */
-	ID_V1 = 5,
+	PLV1_ID = 5,
 
 	/**
 	 * Certificate payload with certificates (CERT).
 	 */
-	CERTIFICATE_V1 = 6,
+	PLV1_CERTIFICATE = 6,
 
 	/**
 	 * Certificate request payload.
 	 */
-	CERTIFICATE_REQUEST_V1 = 7,
+	PLV1_CERTREQ = 7,
 
 	/**
 	 * Hash payload.
 	 */
-	HASH_V1 = 8,
+	PLV1_HASH = 8,
 
 	/**
 	 * Signature payload
 	 */
-	SIGNATURE_V1 = 9,
+	PLV1_SIGNATURE = 9,
 
 	/**
 	 * Nonce payload.
 	 */
-	NONCE_V1 = 10,
+	PLV1_NONCE = 10,
 
 	/**
 	 * Notification payload.
 	 */
-	NOTIFY_V1 = 11,
+	PLV1_NOTIFY = 11,
 
 	/**
 	 * Delete payload.
 	 */
-	DELETE_V1 = 12,
+	PLV1_DELETE = 12,
 
 	/**
 	 * Vendor id payload.
 	 */
-	VENDOR_ID_V1 = 13,
+	PLV1_VENDOR_ID = 13,
 
 	/**
 	 * Attribute payload (ISAKMP Mode Config, aka configuration payload.
 	 */
-	CONFIGURATION_V1 = 14,
+	PLV1_CONFIGURATION = 14,
 
 	/**
 	 * NAT discovery payload (NAT-D).
 	 */
-	NAT_D_V1 = 20,
+	PLV1_NAT_D = 20,
 
 	/**
 	 * NAT original address payload (NAT-OA).
 	 */
-	NAT_OA_V1 = 21,
+	PLV1_NAT_OA = 21,
 
 	/**
 	 * The security association (SA) payload containing proposals.
 	 */
-	SECURITY_ASSOCIATION = 33,
+	PLV2_SECURITY_ASSOCIATION = 33,
 
 	/**
 	 * The key exchange (KE) payload containing diffie-hellman values.
 	 */
-	KEY_EXCHANGE = 34,
+	PLV2_KEY_EXCHANGE = 34,
 
 	/**
 	 * Identification for the original initiator (IDi).
 	 */
-	ID_INITIATOR = 35,
+	PLV2_ID_INITIATOR = 35,
 
 	/**
 	 * Identification for the original responder (IDr).
 	 */
-	ID_RESPONDER = 36,
+	PLV2_ID_RESPONDER = 36,
 
 	/**
 	 * Certificate payload with certificates (CERT).
 	 */
-	CERTIFICATE = 37,
+	PLV2_CERTIFICATE = 37,
 
 	/**
 	 * Certificate request payload (CERTREQ).
 	 */
-	CERTIFICATE_REQUEST = 38,
+	PLV2_CERTREQ = 38,
 
 	/**
 	 * Authentication payload contains auth data (AUTH).
 	 */
-	AUTHENTICATION = 39,
+	PLV2_AUTH = 39,
 
 	/**
 	 * Nonces, for initiator and responder (Ni, Nr, N)
 	 */
-	NONCE = 40,
+	PLV2_NONCE = 40,
 
 	/**
 	 * Notify paylaod (N).
 	 */
-	NOTIFY = 41,
+	PLV2_NOTIFY = 41,
 
 	/**
 	 * Delete payload (D)
 	 */
-	DELETE = 42,
+	PLV2_DELETE = 42,
 
 	/**
 	 * Vendor id paylpoad (V).
 	 */
-	VENDOR_ID = 43,
+	PLV2_VENDOR_ID = 43,
 
 	/**
 	 * Traffic selector for the original initiator (TSi).
 	 */
-	TRAFFIC_SELECTOR_INITIATOR = 44,
+	PLV2_TS_INITIATOR = 44,
 
 	/**
 	 * Traffic selector for the original responser (TSr).
 	 */
-	TRAFFIC_SELECTOR_RESPONDER = 45,
+	PLV2_TS_RESPONDER = 45,
 
 	/**
 	 * Encryption payload, contains other payloads (E).
 	 */
-	ENCRYPTED = 46,
+	PLV2_ENCRYPTED = 46,
 
 	/**
 	 * Configuration payload (CP).
 	 */
-	CONFIGURATION = 47,
+	PLV2_CONFIGURATION = 47,
 
 	/**
 	 * Extensible authentication payload (EAP).
 	 */
-	EXTENSIBLE_AUTHENTICATION = 48,
+	PLV2_EAP = 48,
 
 	/**
 	 * Generic Secure Password Method (GSPM).
 	 */
-	GENERIC_SECURE_PASSWORD_METHOD = 49,
+	PLV2_GSPM = 49,
 
 #ifdef ME
 	/**
 	 * Identification payload for peers has a value from
 	 * the PRIVATE USE space.
 	 */
-	ID_PEER = 128,
+	PLV2_ID_PEER = 128,
 #endif /* ME */
 
 	/**
 	 * NAT discovery payload (NAT-D) (drafts).
 	 */
-	NAT_D_DRAFT_00_03_V1 = 130,
+	PLV1_NAT_D_DRAFT_00_03 = 130,
 
 	/**
 	 * NAT original address payload (NAT-OA) (drafts).
 	 */
-	NAT_OA_DRAFT_00_03_V1 = 131,
+	PLV1_NAT_OA_DRAFT_00_03 = 131,
 
 	/**
 	 * IKE fragment (proprietary IKEv1 extension)
 	 */
-	FRAGMENT_V1 = 132,
+	PLV1_FRAGMENT = 132,
 
 	/**
 	 * Header has a value of PRIVATE USE space.
@@ -241,57 +241,57 @@ enum payload_type_t {
 	 * This type and all the following are never sent over wire and are
 	 * used internally only.
 	 */
-	HEADER = 256,
+	PL_HEADER = 256,
 
 	/**
-	 * PROPOSAL_SUBSTRUCTURE, IKEv2 proposals in a SA payload.
+	 * PLV2_PROPOSAL_SUBSTRUCTURE, IKEv2 proposals in a SA payload.
 	 */
-	PROPOSAL_SUBSTRUCTURE,
+	PLV2_PROPOSAL_SUBSTRUCTURE,
 
 	/**
-	 * PROPOSAL_SUBSTRUCTURE_V1, IKEv1 proposals in a SA payload.
+	 * PLV1_PROPOSAL_SUBSTRUCTURE, IKEv1 proposals in a SA payload.
 	 */
-	PROPOSAL_SUBSTRUCTURE_V1,
+	PLV1_PROPOSAL_SUBSTRUCTURE,
 
 	/**
-	 * TRANSFORM_SUBSTRUCTURE, IKEv2 transforms in a proposal substructure.
+	 * PLV2_TRANSFORM_SUBSTRUCTURE, IKEv2 transforms in a proposal substructure.
 	 */
-	TRANSFORM_SUBSTRUCTURE,
+	PLV2_TRANSFORM_SUBSTRUCTURE,
 
 	/**
-	 * TRANSFORM_SUBSTRUCTURE_V1, IKEv1 transforms in a proposal substructure.
+	 * PLV1_TRANSFORM_SUBSTRUCTURE, IKEv1 transforms in a proposal substructure.
 	 */
-	TRANSFORM_SUBSTRUCTURE_V1,
+	PLV1_TRANSFORM_SUBSTRUCTURE,
 
 	/**
-	 * TRANSFORM_ATTRIBUTE, IKEv2 attribute in a transform.
+	 * PLV2_TRANSFORM_ATTRIBUTE, IKEv2 attribute in a transform.
 	 */
-	TRANSFORM_ATTRIBUTE,
+	PLV2_TRANSFORM_ATTRIBUTE,
 
 	/**
-	 * TRANSFORM_ATTRIBUTE_V1, IKEv1 attribute in a transform.
+	 * PLV1_TRANSFORM_ATTRIBUTE, IKEv1 attribute in a transform.
 	 */
-	TRANSFORM_ATTRIBUTE_V1,
+	PLV1_TRANSFORM_ATTRIBUTE,
 
 	/**
-	 * TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic selector in a TS payload.
+	 * PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE, traffic selector in a TS payload.
 	 */
-	TRAFFIC_SELECTOR_SUBSTRUCTURE,
+	PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE,
 
 	/**
-	 * CONFIGURATION_ATTRIBUTE, IKEv2 attribute in a configuration payload.
+	 * PLV2_CONFIGURATION_ATTRIBUTE, IKEv2 attribute in a configuration payload.
 	 */
-	CONFIGURATION_ATTRIBUTE,
+	PLV2_CONFIGURATION_ATTRIBUTE,
 
 	/**
-	 * CONFIGURATION_ATTRIBUTE_V1, IKEv1 attribute in a configuration payload.
+	 * PLV1_CONFIGURATION_ATTRIBUTE, IKEv1 attribute in a configuration payload.
 	 */
-	CONFIGURATION_ATTRIBUTE_V1,
+	PLV1_CONFIGURATION_ATTRIBUTE,
 
 	/**
 	 * This is not really a payload, but rather the complete IKEv1 message.
 	 */
-	ENCRYPTED_V1,
+	PLV1_ENCRYPTED,
 };
 
 /**
@@ -336,7 +336,7 @@ struct payload_t {
 	payload_type_t (*get_type) (payload_t *this);
 
 	/**
-	 * Get type of next payload or NO_PAYLOAD (0) if this is the last one.
+	 * Get type of next payload or PL_NONE (0) if this is the last one.
 	 *
 	 * @return				type of next payload
 	 */
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
index 3e35b75..53e8cf3 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.c
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -88,7 +88,7 @@ struct private_proposal_substructure_t {
 	linked_list_t *transforms;
 
 	/**
-	 * Type of this payload, PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
+	 * Type of this payload, PLV2_PROPOSAL_SUBSTRUCTURE or PLV1_PROPOSAL_SUBSTRUCTURE
 	 */
 	payload_type_t type;
 };
@@ -114,7 +114,7 @@ static encoding_rule_t encodings_v1[] = {
 	/* SPI is a chunk of variable size*/
 	{ SPI,				offsetof(private_proposal_substructure_t, spi)				},
 	/* Transforms are stored in a transform substructure list */
-	{ PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE_V1,
+	{ PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE,
 						offsetof(private_proposal_substructure_t, transforms)		},
 };
 
@@ -139,7 +139,7 @@ static encoding_rule_t encodings_v2[] = {
 	/* SPI is a chunk of variable size*/
 	{ SPI,				offsetof(private_proposal_substructure_t, spi)				},
 	/* Transforms are stored in a transform substructure list */
-	{ PAYLOAD_LIST + TRANSFORM_SUBSTRUCTURE,
+	{ PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE,
 						offsetof(private_proposal_substructure_t, transforms)		},
 };
 
@@ -329,7 +329,7 @@ METHOD(payload_t, verify, status_t,
 	enumerator_t *enumerator;
 	payload_t *current;
 
-	if (this->next_payload != NO_PAYLOAD && this->next_payload != 2)
+	if (this->next_payload != PL_NONE && this->next_payload != 2)
 	{
 		/* must be 0 or 2 */
 		DBG1(DBG_ENC, "inconsistent next payload");
@@ -361,7 +361,7 @@ METHOD(payload_t, verify, status_t,
 			}
 			break;
 		case PROTO_IKE:
-			if (this->type == PROPOSAL_SUBSTRUCTURE_V1)
+			if (this->type == PLV1_PROPOSAL_SUBSTRUCTURE)
 			{
 				if (this->spi.len <= 16)
 				{	/* according to RFC 2409, section 3.5 anything between
@@ -397,7 +397,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_proposal_substructure_t *this, encoding_rule_t **rules)
 {
-	if (this->type == PROPOSAL_SUBSTRUCTURE)
+	if (this->type == PLV2_PROPOSAL_SUBSTRUCTURE)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -1028,7 +1028,7 @@ METHOD(proposal_substructure_t, get_proposals, void,
 			proposal->set_spi(proposal, spi);
 			proposals->insert_last(proposals, proposal);
 		}
-		if (this->type == PROPOSAL_SUBSTRUCTURE)
+		if (this->type == PLV2_PROPOSAL_SUBSTRUCTURE)
 		{
 			add_to_proposal_v2(proposal, transform);
 		}
@@ -1266,7 +1266,7 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type)
 			.get_encap_mode = _get_encap_mode,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.transforms = linked_list_create(),
 		.type = type,
 	);
@@ -1286,7 +1286,7 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
 	u_int16_t alg, key_size;
 	enumerator_t *enumerator;
 
-	transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
+	transform = transform_substructure_create_type(PLV1_TRANSFORM_SUBSTRUCTURE,
 												number, IKEV1_TRANSID_KEY_IKE);
 
 	enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
@@ -1296,12 +1296,12 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
 		if (alg)
 		{
 			transform->add_transform_attribute(transform,
-				transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+				transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 									TATTR_PH1_ENCRYPTION_ALGORITHM, alg));
 			if (key_size)
 			{
 				transform->add_transform_attribute(transform,
-					transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+					transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 										TATTR_PH1_KEY_LENGTH, key_size));
 			}
 			break;
@@ -1317,7 +1317,7 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
 		if (alg)
 		{
 			transform->add_transform_attribute(transform,
-				transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+				transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 									TATTR_PH1_HASH_ALGORITHM, alg));
 			break;
 		}
@@ -1328,19 +1328,19 @@ static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
 	if (enumerator->enumerate(enumerator, &alg, &key_size))
 	{
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 								TATTR_PH1_GROUP, alg));
 	}
 	enumerator->destroy(enumerator);
 
 	transform->add_transform_attribute(transform,
-		transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+		transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH1_AUTH_METHOD, get_ikev1_auth(method)));
 	transform->add_transform_attribute(transform,
-		transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+		transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH1_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
 	transform->add_transform_attribute(transform,
-		transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+		transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH1_LIFE_DURATION, lifetime));
 
 	add_transform_substructure(this, transform);
@@ -1366,11 +1366,11 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
 		if (alg)
 		{
 			transform = transform_substructure_create_type(
-									TRANSFORM_SUBSTRUCTURE_V1, number, alg);
+									PLV1_TRANSFORM_SUBSTRUCTURE, number, alg);
 			if (key_size)
 			{
 				transform->add_transform_attribute(transform,
-					transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+					transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 											TATTR_PH2_KEY_LENGTH, key_size));
 			}
 		}
@@ -1386,10 +1386,10 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
 			if (!transform)
 			{
 				transform = transform_substructure_create_type(
-									TRANSFORM_SUBSTRUCTURE_V1, number, alg);
+									PLV1_TRANSFORM_SUBSTRUCTURE, number, alg);
 			}
 			transform->add_transform_attribute(transform,
-				transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+				transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 									TATTR_PH2_AUTH_ALGORITHM, alg));
 		}
 	}
@@ -1404,30 +1404,30 @@ static void set_from_proposal_v1(private_proposal_substructure_t *this,
 	if (enumerator->enumerate(enumerator, &alg, &key_size))
 	{
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 									TATTR_PH2_GROUP, alg));
 	}
 	enumerator->destroy(enumerator);
 
 	transform->add_transform_attribute(transform,
-		transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+		transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
 	if (lifetime)
 	{
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_DURATION, lifetime));
 	}
 	if (lifebytes)
 	{
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
 	}
 
@@ -1448,12 +1448,12 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
 	enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
 	while (enumerator->enumerate(enumerator, &alg, &key_size))
 	{
-		transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+		transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
 												ENCRYPTION_ALGORITHM, alg);
 		if (key_size)
 		{
 			transform->add_transform_attribute(transform,
-				transform_attribute_create_value(TRANSFORM_ATTRIBUTE,
+				transform_attribute_create_value(PLV2_TRANSFORM_ATTRIBUTE,
 											TATTR_IKEV2_KEY_LENGTH, key_size));
 		}
 		add_transform_substructure(this, transform);
@@ -1464,7 +1464,7 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
 	enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
 	while (enumerator->enumerate(enumerator, &alg, &key_size))
 	{
-		transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+		transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
 												INTEGRITY_ALGORITHM, alg);
 		add_transform_substructure(this, transform);
 	}
@@ -1474,7 +1474,7 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
 	enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION);
 	while (enumerator->enumerate(enumerator, &alg, &key_size))
 	{
-		transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+		transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
 												PSEUDO_RANDOM_FUNCTION, alg);
 		add_transform_substructure(this, transform);
 	}
@@ -1484,7 +1484,7 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
 	enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
 	while (enumerator->enumerate(enumerator, &alg, NULL))
 	{
-		transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+		transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
 												DIFFIE_HELLMAN_GROUP, alg);
 		add_transform_substructure(this, transform);
 	}
@@ -1494,7 +1494,7 @@ static void set_from_proposal_v2(private_proposal_substructure_t *this,
 	enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS);
 	while (enumerator->enumerate(enumerator, &alg, NULL))
 	{
-		transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE,
+		transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
 												EXTENDED_SEQUENCE_NUMBERS, alg);
 		add_transform_substructure(this, transform);
 	}
@@ -1543,7 +1543,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
 	private_proposal_substructure_t *this;
 
 	this = (private_proposal_substructure_t*)
-							proposal_substructure_create(SECURITY_ASSOCIATION);
+							proposal_substructure_create(PLV2_SECURITY_ASSOCIATION);
 	set_from_proposal_v2(this, proposal);
 	set_data(this, proposal);
 
@@ -1560,7 +1560,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
 	private_proposal_substructure_t *this;
 
 	this = (private_proposal_substructure_t*)
-						proposal_substructure_create(PROPOSAL_SUBSTRUCTURE_V1);
+						proposal_substructure_create(PLV1_PROPOSAL_SUBSTRUCTURE);
 	switch (proposal->get_protocol(proposal))
 	{
 		case PROTO_IKE:
@@ -1636,31 +1636,31 @@ proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
 
 
 	this = (private_proposal_substructure_t*)
-						proposal_substructure_create(PROPOSAL_SUBSTRUCTURE_V1);
+						proposal_substructure_create(PLV1_PROPOSAL_SUBSTRUCTURE);
 
 	/* we currently support DEFLATE only */
-	transform = transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1,
+	transform = transform_substructure_create_type(PLV1_TRANSFORM_SUBSTRUCTURE,
 												   1, IKEV1_IPCOMP_DEFLATE);
 
 	transform->add_transform_attribute(transform,
-		transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+		transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
 	if (lifetime)
 	{
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_DURATION, lifetime));
 	}
 	if (lifebytes)
 	{
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
 		transform->add_transform_attribute(transform,
-			transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1,
+			transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
 							TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
 	}
 
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.h b/src/libcharon/encoding/payloads/proposal_substructure.h
index c8e7adf..c4614b8 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.h
+++ b/src/libcharon/encoding/payloads/proposal_substructure.h
@@ -168,7 +168,7 @@ struct proposal_substructure_t {
 /**
  * Creates an empty proposal_substructure_t object
  *
- * @param type		PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
+ * @param type		PLV2_PROPOSAL_SUBSTRUCTURE or PLV1_PROPOSAL_SUBSTRUCTURE
  * @return			proposal_substructure_t object
  */
 proposal_substructure_t *proposal_substructure_create(payload_type_t type);
@@ -177,7 +177,7 @@ proposal_substructure_t *proposal_substructure_create(payload_type_t type);
  * Creates an IKEv2 proposal_substructure_t from a proposal_t.
  *
  * @param proposal	proposal to build a substruct out of it
- * @return			proposal_substructure_t PROPOSAL_SUBSTRUCTURE
+ * @return			proposal_substructure_t PLV2_PROPOSAL_SUBSTRUCTURE
  */
 proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
 														proposal_t *proposal);
@@ -190,7 +190,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
  * @param auth		authentication method to use, or AUTH_NONE
  * @param mode		IPsec encapsulation mode, TRANSPORT or TUNNEL
  * @param udp		ENCAP_UDP to use UDP encapsulation
- * @return			proposal_substructure_t object PROPOSAL_SUBSTRUCTURE_V1
+ * @return			proposal_substructure_t object PLV1_PROPOSAL_SUBSTRUCTURE
  */
 proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
 			proposal_t *proposal,  u_int32_t lifetime, u_int64_t lifebytes,
@@ -205,7 +205,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
  * @param auth		authentication method to use, or AUTH_NONE
  * @param mode		IPsec encapsulation mode, TRANSPORT or TUNNEL
  * @param udp		ENCAP_UDP to use UDP encapsulation
- * @return			IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
+ * @return			IKEv1 proposal_substructure_t PLV1_PROPOSAL_SUBSTRUCTURE
  */
 proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
 			linked_list_t *proposals, u_int32_t lifetime, u_int64_t lifebytes,
@@ -221,7 +221,7 @@ proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
  * @param mode				IPsec encapsulation mode, TRANSPORT or TUNNEL
  * @param udp				ENCAP_UDP to use UDP encapsulation
  * @param proposal_number	the proposal number of the proposal to be linked
- * @return					IKEv1 proposal_substructure_t PROPOSAL_SUBSTRUCTURE_V1
+ * @return					IKEv1 proposal_substructure_t PLV1_PROPOSAL_SUBSTRUCTURE
  */
 proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
 			u_int32_t lifetime, u_int64_t lifebytes, u_int16_t cpi,
diff --git a/src/libcharon/encoding/payloads/sa_payload.c b/src/libcharon/encoding/payloads/sa_payload.c
index 3a5bb43..8e3a012 100644
--- a/src/libcharon/encoding/payloads/sa_payload.c
+++ b/src/libcharon/encoding/payloads/sa_payload.c
@@ -101,7 +101,7 @@ static encoding_rule_t encodings_v1[] = {
 	/* Situation*/
 	{ U_INT_32,			offsetof(private_sa_payload_t, situation)		},
 	/* Proposals are stored in a proposal substructure list */
-	{ PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE_V1,
+	{ PAYLOAD_LIST + PLV1_PROPOSAL_SUBSTRUCTURE,
 						offsetof(private_sa_payload_t, proposals)		},
 };
 
@@ -140,7 +140,7 @@ static encoding_rule_t encodings_v2[] = {
 	/* Length of the whole SA payload*/
 	{ PAYLOAD_LENGTH,	offsetof(private_sa_payload_t, payload_length)		},
 	/* Proposals are stored in a proposal substructure list */
-	{ PAYLOAD_LIST + PROPOSAL_SUBSTRUCTURE,
+	{ PAYLOAD_LIST + PLV2_PROPOSAL_SUBSTRUCTURE,
 						offsetof(private_sa_payload_t, proposals)			},
 };
 
@@ -164,7 +164,7 @@ METHOD(payload_t, verify, status_t,
 	enumerator_t *enumerator;
 	proposal_substructure_t *substruct;
 
-	if (this->type == SECURITY_ASSOCIATION)
+	if (this->type == PLV2_SECURITY_ASSOCIATION)
 	{
 		expected_number = 1;
 	}
@@ -196,7 +196,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_sa_payload_t *this, encoding_rule_t **rules)
 {
-	if (this->type == SECURITY_ASSOCIATION_V1)
+	if (this->type == PLV1_SECURITY_ASSOCIATION)
 	{
 		*rules = encodings_v1;
 		return countof(encodings_v1);
@@ -208,7 +208,7 @@ METHOD(payload_t, get_encoding_rules, int,
 METHOD(payload_t, get_header_length, int,
 	private_sa_payload_t *this)
 {
-	if (this->type == SECURITY_ASSOCIATION_V1)
+	if (this->type == PLV1_SECURITY_ASSOCIATION)
 	{
 		return 12;
 	}
@@ -295,7 +295,7 @@ METHOD(sa_payload_t, get_proposals, linked_list_t*,
 	proposal_substructure_t *substruct;
 	linked_list_t *substructs, *list;
 
-	if (this->type == SECURITY_ASSOCIATION_V1)
+	if (this->type == PLV1_SECURITY_ASSOCIATION)
 	{	/* IKEv1 proposals start with 0 */
 		struct_number = ignore_struct_number = -1;
 	}
@@ -502,7 +502,7 @@ sa_payload_t *sa_payload_create(payload_type_t type)
 			.get_encap_mode = _get_encap_mode,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.proposals = linked_list_create(),
 		.type = type,
 		/* for IKEv1 only */
@@ -524,7 +524,7 @@ sa_payload_t *sa_payload_create_from_proposals_v2(linked_list_t *proposals)
 	enumerator_t *enumerator;
 	proposal_t *proposal;
 
-	this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
+	this = (private_sa_payload_t*)sa_payload_create(PLV2_SECURITY_ASSOCIATION);
 	enumerator = proposals->create_enumerator(proposals);
 	while (enumerator->enumerate(enumerator, &proposal))
 	{
@@ -542,7 +542,7 @@ sa_payload_t *sa_payload_create_from_proposal_v2(proposal_t *proposal)
 {
 	private_sa_payload_t *this;
 
-	this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION);
+	this = (private_sa_payload_t*)sa_payload_create(PLV2_SECURITY_ASSOCIATION);
 	add_proposal_v2(this, proposal);
 
 	return &this->public;
@@ -560,7 +560,7 @@ sa_payload_t *sa_payload_create_from_proposals_v1(linked_list_t *proposals,
 	proposal_substructure_t *substruct;
 	private_sa_payload_t *this;
 
-	this = (private_sa_payload_t*)sa_payload_create(SECURITY_ASSOCIATION_V1);
+	this = (private_sa_payload_t*)sa_payload_create(PLV1_SECURITY_ASSOCIATION);
 
 	if (!proposals || !proposals->get_count(proposals))
 	{
diff --git a/src/libcharon/encoding/payloads/sa_payload.h b/src/libcharon/encoding/payloads/sa_payload.h
index b62a341..0ddf361 100644
--- a/src/libcharon/encoding/payloads/sa_payload.h
+++ b/src/libcharon/encoding/payloads/sa_payload.h
@@ -104,7 +104,7 @@ struct sa_payload_t {
 /**
  * Creates an empty sa_payload_t object
  *
- * @param type				SECURITY_ASSOCIATION or SECURITY_ASSOCIATION_V1
+ * @param type				PLV2_SECURITY_ASSOCIATION or PLV1_SECURITY_ASSOCIATION
  * @return					created sa_payload_t object
  */
 sa_payload_t *sa_payload_create(payload_type_t type);
diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
index 334823d..83618ff 100644
--- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c
+++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c
@@ -168,13 +168,13 @@ METHOD(payload_t, get_header_length, int,
 METHOD(payload_t, get_type, payload_type_t,
 	private_traffic_selector_substructure_t *this)
 {
-	return TRAFFIC_SELECTOR_SUBSTRUCTURE;
+	return PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE;
 }
 
 METHOD(payload_t, get_next_type, payload_type_t,
 	private_traffic_selector_substructure_t *this)
 {
-	return NO_PAYLOAD;
+	return PL_NONE;
 }
 
 METHOD(payload_t, set_next_type, void,
diff --git a/src/libcharon/encoding/payloads/transform_attribute.c b/src/libcharon/encoding/payloads/transform_attribute.c
index d20f77c..4a5b52d 100644
--- a/src/libcharon/encoding/payloads/transform_attribute.c
+++ b/src/libcharon/encoding/payloads/transform_attribute.c
@@ -98,7 +98,7 @@ struct private_transform_attribute_t {
 	chunk_t attribute_value;
 
 	/**
-	 * Payload type, TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
+	 * Payload type, PLV2_TRANSFORM_ATTRIBUTE or PLV1_TRANSFORM_ATTRIBUTE
 	 */
 	payload_type_t type;
 };
@@ -157,7 +157,7 @@ METHOD(payload_t, get_type, payload_type_t,
 METHOD(payload_t, get_next_type, payload_type_t,
 	private_transform_attribute_t *this)
 {
-	return NO_PAYLOAD;
+	return PL_NONE;
 }
 
 METHOD(payload_t, set_next_type, void,
diff --git a/src/libcharon/encoding/payloads/transform_attribute.h b/src/libcharon/encoding/payloads/transform_attribute.h
index 23897a5..87e283b 100644
--- a/src/libcharon/encoding/payloads/transform_attribute.h
+++ b/src/libcharon/encoding/payloads/transform_attribute.h
@@ -127,7 +127,7 @@ struct transform_attribute_t {
 /**
  * Creates an empty transform_attribute_t object.
  *
- * @param type			TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
+ * @param type			PLV2_TRANSFORM_ATTRIBUTE or PLV1_TRANSFORM_ATTRIBUTE
  * @return				transform_attribute_t object
  */
 transform_attribute_t *transform_attribute_create(payload_type_t type);
@@ -135,7 +135,7 @@ transform_attribute_t *transform_attribute_create(payload_type_t type);
 /**
  * Creates a two byte value or a larger attribute for a given attribute kind.
  *
- * @param type			TRANSFORM_ATTRIBUTE or TRANSFORM_ATTRIBUTE_V1
+ * @param type			PLV2_TRANSFORM_ATTRIBUTE or PLV1_TRANSFORM_ATTRIBUTE
  * @param kind			attribute kind
  * @param value			fixed two byte value
  * @return				transform_attribute_t object
diff --git a/src/libcharon/encoding/payloads/transform_substructure.c b/src/libcharon/encoding/payloads/transform_substructure.c
index a850275..6885d61 100644
--- a/src/libcharon/encoding/payloads/transform_substructure.c
+++ b/src/libcharon/encoding/payloads/transform_substructure.c
@@ -73,13 +73,13 @@ struct private_transform_substructure_t {
 	linked_list_t *attributes;
 
 	/**
-	 * Payload type, TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
+	 * Payload type, PLV2_TRANSFORM_SUBSTRUCTURE or PLV1_TRANSFORM_SUBSTRUCTURE
 	 */
 	payload_type_t type;
 };
 
 /**
- * Encoding rules for TRANSFORM_SUBSTRUCTURE
+ * Encoding rules for PLV2_TRANSFORM_SUBSTRUCTURE
  */
 static encoding_rule_t encodings_v2[] = {
 	/* 1 Byte next payload type, stored in the field next_payload */
@@ -95,12 +95,12 @@ static encoding_rule_t encodings_v2[] = {
 	/* transform identifier, as used by IKEv2 */
 	{ U_INT_16,			offsetof(private_transform_substructure_t, transform_id_v2)	},
 	/* Attributes in a transform attribute list */
-	{ PAYLOAD_LIST + TRANSFORM_ATTRIBUTE,
+	{ PAYLOAD_LIST + PLV2_TRANSFORM_ATTRIBUTE,
 						offsetof(private_transform_substructure_t, attributes)		}
 };
 
 /**
- * Encoding rules for TRANSFORM_SUBSTRUCTURE_V1
+ * Encoding rules for PLV1_TRANSFORM_SUBSTRUCTURE
  */
 static encoding_rule_t encodings_v1[] = {
 	/* 1 Byte next payload type, stored in the field next_payload */
@@ -117,7 +117,7 @@ static encoding_rule_t encodings_v1[] = {
 	{ RESERVED_BYTE,	offsetof(private_transform_substructure_t, reserved[1])		},
 	{ RESERVED_BYTE,	offsetof(private_transform_substructure_t, reserved[2])		},
 	/* Attributes in a transform attribute list */
-	{ PAYLOAD_LIST + TRANSFORM_ATTRIBUTE_V1,
+	{ PAYLOAD_LIST + PLV1_TRANSFORM_ATTRIBUTE,
 						offsetof(private_transform_substructure_t, attributes)		}
 };
 
@@ -142,7 +142,7 @@ METHOD(payload_t, verify, status_t,
 	enumerator_t *enumerator;
 	payload_t *attribute;
 
-	if (this->next_payload != NO_PAYLOAD && this->next_payload != 3)
+	if (this->next_payload != PL_NONE && this->next_payload != 3)
 	{
 		DBG1(DBG_ENC, "inconsistent next payload");
 		return FAILED;
@@ -167,7 +167,7 @@ METHOD(payload_t, verify, status_t,
 METHOD(payload_t, get_encoding_rules, int,
 	private_transform_substructure_t *this, encoding_rule_t **rules)
 {
-	if (this->type == TRANSFORM_SUBSTRUCTURE)
+	if (this->type == PLV2_TRANSFORM_SUBSTRUCTURE)
 	{
 		*rules = encodings_v2;
 		return countof(encodings_v2);
@@ -244,7 +244,7 @@ METHOD(transform_substructure_t, get_transform_type_or_number, u_int8_t,
 METHOD(transform_substructure_t, get_transform_id, u_int16_t,
 	private_transform_substructure_t *this)
 {
-	if (this->type == TRANSFORM_SUBSTRUCTURE)
+	if (this->type == PLV2_TRANSFORM_SUBSTRUCTURE)
 	{
 		return this->transform_id_v2;
 	}
@@ -291,7 +291,7 @@ transform_substructure_t *transform_substructure_create(payload_type_t type)
 			.create_attribute_enumerator = _create_attribute_enumerator,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.transform_length = get_header_length(this),
 		.attributes = linked_list_create(),
 		.type = type,
@@ -310,7 +310,7 @@ transform_substructure_t *transform_substructure_create_type(payload_type_t type
 	this = (private_transform_substructure_t*)transform_substructure_create(type);
 
 	this->transform_ton = type_or_number;
-	if (type == TRANSFORM_SUBSTRUCTURE)
+	if (type == PLV2_TRANSFORM_SUBSTRUCTURE)
 	{
 		this->transform_id_v2 = id;
 	}
diff --git a/src/libcharon/encoding/payloads/transform_substructure.h b/src/libcharon/encoding/payloads/transform_substructure.h
index 97717e6..ba821d3 100644
--- a/src/libcharon/encoding/payloads/transform_substructure.h
+++ b/src/libcharon/encoding/payloads/transform_substructure.h
@@ -97,7 +97,7 @@ struct transform_substructure_t {
 /**
  * Creates an empty transform_substructure_t object.
  *
- * @param type			TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
+ * @param type			PLV2_TRANSFORM_SUBSTRUCTURE or PLV1_TRANSFORM_SUBSTRUCTURE
  * @return				created transform_substructure_t object
  */
 transform_substructure_t *transform_substructure_create(payload_type_t type);
@@ -105,7 +105,7 @@ transform_substructure_t *transform_substructure_create(payload_type_t type);
 /**
  * Creates an empty transform_substructure_t object.
  *
- * @param type				TRANSFORM_SUBSTRUCTURE or TRANSFORM_SUBSTRUCTURE_V1
+ * @param type				PLV2_TRANSFORM_SUBSTRUCTURE or PLV1_TRANSFORM_SUBSTRUCTURE
  * @param type_or_number	Type (IKEv2) or number (IKEv1) of transform
  * @param id				transform id specifc for the transform type
  * @return					transform_substructure_t object
diff --git a/src/libcharon/encoding/payloads/ts_payload.c b/src/libcharon/encoding/payloads/ts_payload.c
index 8dfa47b..e74b9ae 100644
--- a/src/libcharon/encoding/payloads/ts_payload.c
+++ b/src/libcharon/encoding/payloads/ts_payload.c
@@ -103,7 +103,7 @@ static encoding_rule_t encodings[] = {
 	{ RESERVED_BYTE,	offsetof(private_ts_payload_t, reserved_byte[1])},
 	{ RESERVED_BYTE,	offsetof(private_ts_payload_t, reserved_byte[2])},
 	/* wrapped list of traffic selectors substructures */
-	{ PAYLOAD_LIST + TRAFFIC_SELECTOR_SUBSTRUCTURE,
+	{ PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE,
 						offsetof(private_ts_payload_t, substrs)			},
 };
 
@@ -164,9 +164,9 @@ METHOD(payload_t, get_type, payload_type_t,
 {
 	if (this->is_initiator)
 	{
-		return TRAFFIC_SELECTOR_INITIATOR;
+		return PLV2_TS_INITIATOR;
 	}
-	return TRAFFIC_SELECTOR_RESPONDER;
+	return PLV2_TS_RESPONDER;
 }
 
 METHOD(payload_t, get_next_type, payload_type_t,
@@ -269,7 +269,7 @@ ts_payload_t *ts_payload_create(bool is_initiator)
 			.get_traffic_selectors = _get_traffic_selectors,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.is_initiator = is_initiator,
 		.substrs = linked_list_create(),
diff --git a/src/libcharon/encoding/payloads/unknown_payload.c b/src/libcharon/encoding/payloads/unknown_payload.c
index fe7ced2..45b91fd 100644
--- a/src/libcharon/encoding/payloads/unknown_payload.c
+++ b/src/libcharon/encoding/payloads/unknown_payload.c
@@ -184,7 +184,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
 			.get_data = _get_data,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this),
 		.type = type,
 	);
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.c b/src/libcharon/encoding/payloads/vendor_id_payload.c
index 0c1df56..400e064 100644
--- a/src/libcharon/encoding/payloads/vendor_id_payload.c
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.c
@@ -178,7 +178,7 @@ vendor_id_payload_t *vendor_id_payload_create_data(payload_type_t type,
 			.get_data = _get_data,
 			.destroy = _destroy,
 		},
-		.next_payload = NO_PAYLOAD,
+		.next_payload = PL_NONE,
 		.payload_length = get_header_length(this) + data.len,
 		.data = data,
 		.type = type,
diff --git a/src/libcharon/encoding/payloads/vendor_id_payload.h b/src/libcharon/encoding/payloads/vendor_id_payload.h
index 9a81477..42c31f9 100644
--- a/src/libcharon/encoding/payloads/vendor_id_payload.h
+++ b/src/libcharon/encoding/payloads/vendor_id_payload.h
@@ -55,7 +55,7 @@ struct vendor_id_payload_t {
 /**
  * Creates an empty Vendor ID payload for IKEv1 or IKEv2.
  *
- * @@param type		VENDOR_ID or VENDOR_ID_V1
+ * @@param type		PLV2_VENDOR_ID or PLV1_VENDOR_ID
  * @return			vendor ID payload
  */
 vendor_id_payload_t *vendor_id_payload_create(payload_type_t type);
@@ -63,7 +63,7 @@ vendor_id_payload_t *vendor_id_payload_create(payload_type_t type);
 /**
  * Creates a vendor ID payload using a chunk of data
  *
- * @param type		VENDOR_ID or VENDOR_ID_V1
+ * @param type		PLV2_VENDOR_ID or PLV1_VENDOR_ID
  * @param data		data to use in vendor ID payload, gets owned by payload
  * @return			vendor ID payload
  */
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index 8dfb47b..a2a3b1f 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -271,7 +271,7 @@ static bool check_cookie(private_receiver_t *this, message_t *message)
 	if (data.len <
 		 IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH +
 		 sizeof(u_int32_t) + this->hasher->get_hash_size(this->hasher) ||
-		*(data.ptr + 16) != NOTIFY ||
+		*(data.ptr + 16) != PLV2_NOTIFY ||
 		*(u_int16_t*)(data.ptr + IKE_HEADER_LENGTH + 6) != htons(COOKIE))
 	{
 		/* no cookie found */
diff --git a/src/libcharon/plugins/addrblock/Makefile.am b/src/libcharon/plugins/addrblock/Makefile.am
index 407f22d..33ee60d 100644
--- a/src/libcharon/plugins/addrblock/Makefile.am
+++ b/src/libcharon/plugins/addrblock/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-addrblock.la
diff --git a/src/libcharon/plugins/addrblock/Makefile.in b/src/libcharon/plugins/addrblock/Makefile.in
index 0aa635a..0655959 100644
--- a/src/libcharon/plugins/addrblock/Makefile.in
+++ b/src/libcharon/plugins/addrblock/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-addrblock.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-addrblock.la
diff --git a/src/libcharon/plugins/android_dns/Makefile.am b/src/libcharon/plugins/android_dns/Makefile.am
index ebad963..1a0d6e6 100644
--- a/src/libcharon/plugins/android_dns/Makefile.am
+++ b/src/libcharon/plugins/android_dns/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-android-dns.la
diff --git a/src/libcharon/plugins/android_dns/Makefile.in b/src/libcharon/plugins/android_dns/Makefile.in
index f44734c..287c94a 100644
--- a/src/libcharon/plugins/android_dns/Makefile.in
+++ b/src/libcharon/plugins/android_dns/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-android-dns.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-android-dns.la
diff --git a/src/libcharon/plugins/android_log/Makefile.am b/src/libcharon/plugins/android_log/Makefile.am
index 4d8b485..79c61b5 100644
--- a/src/libcharon/plugins/android_log/Makefile.am
+++ b/src/libcharon/plugins/android_log/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-android-log.la
diff --git a/src/libcharon/plugins/android_log/Makefile.in b/src/libcharon/plugins/android_log/Makefile.in
index 361b361..9fd5150 100644
--- a/src/libcharon/plugins/android_log/Makefile.in
+++ b/src/libcharon/plugins/android_log/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-android-log.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-android-log.la
diff --git a/src/libcharon/plugins/certexpire/Makefile.am b/src/libcharon/plugins/certexpire/Makefile.am
index 2bfad94..b8c241d 100644
--- a/src/libcharon/plugins/certexpire/Makefile.am
+++ b/src/libcharon/plugins/certexpire/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-certexpire.la
diff --git a/src/libcharon/plugins/certexpire/Makefile.in b/src/libcharon/plugins/certexpire/Makefile.in
index e218c8a..edda93e 100644
--- a/src/libcharon/plugins/certexpire/Makefile.in
+++ b/src/libcharon/plugins/certexpire/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-certexpire.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-certexpire.la
diff --git a/src/libcharon/plugins/coupling/Makefile.am b/src/libcharon/plugins/coupling/Makefile.am
index cbc06a6..badc7b7 100644
--- a/src/libcharon/plugins/coupling/Makefile.am
+++ b/src/libcharon/plugins/coupling/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-coupling.la
diff --git a/src/libcharon/plugins/coupling/Makefile.in b/src/libcharon/plugins/coupling/Makefile.in
index bb95126..5670f43 100644
--- a/src/libcharon/plugins/coupling/Makefile.in
+++ b/src/libcharon/plugins/coupling/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-coupling.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-coupling.la
diff --git a/src/libcharon/plugins/coupling/coupling_validator.c b/src/libcharon/plugins/coupling/coupling_validator.c
index fc35462..0686e0f 100644
--- a/src/libcharon/plugins/coupling/coupling_validator.c
+++ b/src/libcharon/plugins/coupling/coupling_validator.c
@@ -202,6 +202,7 @@ METHOD(coupling_validator_t, destroy, void,
 coupling_validator_t *coupling_validator_create()
 {
 	private_coupling_validator_t *this;
+	hash_algorithm_t alg;
 	char *path, *hash;
 
 	INIT(this,
@@ -219,8 +220,13 @@ coupling_validator_t *coupling_validator_create()
 
 	hash = lib->settings->get_str(lib->settings,
 								  "%s.plugins.coupling.hash", "sha1", lib->ns);
-	this->hasher = lib->crypto->create_hasher(lib->crypto,
-							enum_from_name(hash_algorithm_short_names, hash));
+	if (!enum_from_name(hash_algorithm_short_names, hash, &alg))
+	{
+		DBG1(DBG_CFG, "unknown coupling hash algorithm: %s", hash);
+		destroy(this);
+		return NULL;
+	}
+	this->hasher = lib->crypto->create_hasher(lib->crypto, alg);
 	if (!this->hasher)
 	{
 		DBG1(DBG_CFG, "unsupported coupling hash algorithm: %s", hash);
diff --git a/src/libcharon/plugins/dhcp/Makefile.am b/src/libcharon/plugins/dhcp/Makefile.am
index e0e857e..3c09db0 100644
--- a/src/libcharon/plugins/dhcp/Makefile.am
+++ b/src/libcharon/plugins/dhcp/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-dhcp.la
diff --git a/src/libcharon/plugins/dhcp/Makefile.in b/src/libcharon/plugins/dhcp/Makefile.in
index 81f2b78..da364b0 100644
--- a/src/libcharon/plugins/dhcp/Makefile.in
+++ b/src/libcharon/plugins/dhcp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-dhcp.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-dhcp.la
diff --git a/src/libcharon/plugins/dnscert/Makefile.am b/src/libcharon/plugins/dnscert/Makefile.am
index 51d542b..1455625 100644
--- a/src/libcharon/plugins/dnscert/Makefile.am
+++ b/src/libcharon/plugins/dnscert/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-dnscert.la
diff --git a/src/libcharon/plugins/dnscert/Makefile.in b/src/libcharon/plugins/dnscert/Makefile.in
index d9eeddf..d408cd2 100644
--- a/src/libcharon/plugins/dnscert/Makefile.in
+++ b/src/libcharon/plugins/dnscert/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-dnscert.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-dnscert.la
diff --git a/src/libcharon/plugins/duplicheck/Makefile.am b/src/libcharon/plugins/duplicheck/Makefile.am
index 4ea2bec..338a114 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.am
+++ b/src/libcharon/plugins/duplicheck/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-duplicheck.la
diff --git a/src/libcharon/plugins/duplicheck/Makefile.in b/src/libcharon/plugins/duplicheck/Makefile.in
index 0b12cf3..97432f1 100644
--- a/src/libcharon/plugins/duplicheck/Makefile.in
+++ b/src/libcharon/plugins/duplicheck/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -273,6 +273,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -291,6 +292,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -318,6 +320,7 @@ 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@
@@ -409,6 +412,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -426,7 +430,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-duplicheck.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-duplicheck.la
diff --git a/src/libcharon/plugins/eap_aka/Makefile.am b/src/libcharon/plugins/eap_aka/Makefile.am
index ba6e660..75e8eaf 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.am
+++ b/src/libcharon/plugins/eap_aka/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-aka.la
diff --git a/src/libcharon/plugins/eap_aka/Makefile.in b/src/libcharon/plugins/eap_aka/Makefile.in
index 9e771ae..5b20fe5 100644
--- a/src/libcharon/plugins/eap_aka/Makefile.in
+++ b/src/libcharon/plugins/eap_aka/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-aka.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-aka.la
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
index 4e2b207..ec145a3 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version
 libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
index 91c4bb1..d0ee198 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
+++ b/src/libcharon/plugins/eap_aka_3gpp2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 libstrongswan_eap_aka_3gpp2_la_LDFLAGS = -module -avoid-version
 libstrongswan_eap_aka_3gpp2_la_LIBADD = -lgmp $(am__append_1)
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.am b/src/libcharon/plugins/eap_dynamic/Makefile.am
index 13b4d10..58b827a 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.am
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-dynamic.la
diff --git a/src/libcharon/plugins/eap_dynamic/Makefile.in b/src/libcharon/plugins/eap_dynamic/Makefile.in
index 16d0b42..78b66ac 100644
--- a/src/libcharon/plugins/eap_dynamic/Makefile.in
+++ b/src/libcharon/plugins/eap_dynamic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-dynamic.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-dynamic.la
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.am b/src/libcharon/plugins/eap_gtc/Makefile.am
index 811366a..c3a12ba 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.am
+++ b/src/libcharon/plugins/eap_gtc/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-gtc.la
diff --git a/src/libcharon/plugins/eap_gtc/Makefile.in b/src/libcharon/plugins/eap_gtc/Makefile.in
index 1c8d51b..7f18792 100644
--- a/src/libcharon/plugins/eap_gtc/Makefile.in
+++ b/src/libcharon/plugins/eap_gtc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-gtc.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-gtc.la
diff --git a/src/libcharon/plugins/eap_gtc/eap_gtc.c b/src/libcharon/plugins/eap_gtc/eap_gtc.c
index e751b51..5fcd9eb 100644
--- a/src/libcharon/plugins/eap_gtc/eap_gtc.c
+++ b/src/libcharon/plugins/eap_gtc/eap_gtc.c
@@ -161,11 +161,11 @@ METHOD(eap_method_t, process_server, status_t,
 	{
 		/* assume that "out" contains username/password attributes */
 		co->destroy(co);
-		ci = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+		ci = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
 		ci->add_attribute(ci, configuration_attribute_create_chunk(
-					CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
+					PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, user));
 		ci->add_attribute(ci, configuration_attribute_create_chunk(
-					CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
+					PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, pass));
 		switch (xauth->process(xauth, ci, &co))
 		{
 			case SUCCESS:
diff --git a/src/libcharon/plugins/eap_identity/Makefile.am b/src/libcharon/plugins/eap_identity/Makefile.am
index 1c15586..6c5b43f 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.am
+++ b/src/libcharon/plugins/eap_identity/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS =  \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-identity.la
diff --git a/src/libcharon/plugins/eap_identity/Makefile.in b/src/libcharon/plugins/eap_identity/Makefile.in
index 4c536b2..5275a34 100644
--- a/src/libcharon/plugins/eap_identity/Makefile.in
+++ b/src/libcharon/plugins/eap_identity/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-identity.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-identity.la
diff --git a/src/libcharon/plugins/eap_md5/Makefile.am b/src/libcharon/plugins/eap_md5/Makefile.am
index 5835983..16aa191 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.am
+++ b/src/libcharon/plugins/eap_md5/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-md5.la
diff --git a/src/libcharon/plugins/eap_md5/Makefile.in b/src/libcharon/plugins/eap_md5/Makefile.in
index d9938dd..5dd623d 100644
--- a/src/libcharon/plugins/eap_md5/Makefile.in
+++ b/src/libcharon/plugins/eap_md5/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-md5.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-md5.la
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.am b/src/libcharon/plugins/eap_mschapv2/Makefile.am
index 030682d..4276a08 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.am
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-mschapv2.la
diff --git a/src/libcharon/plugins/eap_mschapv2/Makefile.in b/src/libcharon/plugins/eap_mschapv2/Makefile.in
index 7caac9c..c0e4219 100644
--- a/src/libcharon/plugins/eap_mschapv2/Makefile.in
+++ b/src/libcharon/plugins/eap_mschapv2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-mschapv2.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-mschapv2.la
diff --git a/src/libcharon/plugins/eap_peap/Makefile.am b/src/libcharon/plugins/eap_peap/Makefile.am
index 19410a4..8960b84 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.am
+++ b/src/libcharon/plugins/eap_peap/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-peap.la
diff --git a/src/libcharon/plugins/eap_peap/Makefile.in b/src/libcharon/plugins/eap_peap/Makefile.in
index 29d8c8b..615a916 100644
--- a/src/libcharon/plugins/eap_peap/Makefile.in
+++ b/src/libcharon/plugins/eap_peap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-peap.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-peap.la
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_avp.c b/src/libcharon/plugins/eap_peap/eap_peap_avp.c
index f7f634a..3f541ba 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_avp.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap_avp.c
@@ -25,8 +25,6 @@ static const chunk_t MS_AVP_Success = chunk_from_chars(
 											0x80, 0x03, 0x00, 0x02, 0x00, 0x01);
 static const chunk_t MS_AVP_Failure = chunk_from_chars(
 											0x80, 0x03, 0x00, 0x02, 0x00, 0x02);
-static const chunk_t MS_SoH_Request = chunk_from_chars(
-			  0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x21, 0x00, 0x02, 0x00, 0x00);
 
 typedef struct private_eap_peap_avp_t private_eap_peap_avp_t;
 
@@ -64,19 +62,6 @@ METHOD(eap_peap_avp_t, build, void,
 		writer->write_uint8(writer, EAP_MSTLV);
 		avp_data = (pkt->code == EAP_SUCCESS) ? MS_AVP_Success : MS_AVP_Failure;
 	}
-	/**
-	 * Still trying to form a correct MS SoH Request
-	 *
-	else if (pkt->type == EAP_MSCHAPV2)
-	{
-		code = (this->is_server) ? EAP_REQUEST : EAP_RESPONSE;
-		writer->write_uint8(writer, code);
-		writer->write_uint8(writer, pkt->identifier);
-		writer->write_uint16(writer, 16);
-		writer->write_uint8(writer, EAP_EXPANDED);
-		avp_data = MS_SoH_Request;
-	}
-	*/
 	else
 	{
 		avp_data = chunk_skip(data, 4);
diff --git a/src/libcharon/plugins/eap_radius/Makefile.am b/src/libcharon/plugins/eap_radius/Makefile.am
index 6fdb0d0..bc7a776 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.am
+++ b/src/libcharon/plugins/eap_radius/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libradius
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-radius.la
diff --git a/src/libcharon/plugins/eap_radius/Makefile.in b/src/libcharon/plugins/eap_radius/Makefile.in
index fbce312..cd4355d 100644
--- a/src/libcharon/plugins/eap_radius/Makefile.in
+++ b/src/libcharon/plugins/eap_radius/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libradius
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-radius.la
 @MONOLITHIC_FALSE at libstrongswan_eap_radius_la_LIBADD = $(top_builddir)/src/libradius/libradius.la
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index 5fb1bbb..0020c5d 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -210,7 +210,7 @@ static void add_ike_sa_parameters(private_eap_radius_accounting_t *this,
 {
 	enumerator_t *enumerator;
 	host_t *vip, *host;
-	char buf[128];
+	char buf[MAX_RADIUS_ATTRIBUTE_SIZE + 1];
 	chunk_t data;
 	u_int32_t value;
 
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_forward.c b/src/libcharon/plugins/eap_radius/eap_radius_forward.c
index 54d52a9..52ea840 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_forward.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_forward.c
@@ -232,8 +232,8 @@ static void ike2queue(message_t *message, linked_list_t *queue,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY ||
-			payload->get_type(payload) == NOTIFY_V1)
+		if (payload->get_type(payload) == PLV2_NOTIFY ||
+			payload->get_type(payload) == PLV1_NOTIFY)
 		{
 			notify = (notify_payload_t*)payload;
 			if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE)
@@ -362,8 +362,7 @@ static linked_list_t* parse_selector(char *selector)
 			vendor = atoi(token);
 			token = pos;
 		}
-		type = enum_from_name(radius_attribute_type_names, token);
-		if (type == -1)
+		if (!enum_from_name(radius_attribute_type_names, token, &type))
 		{
 			type = atoi(token);
 		}
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_xauth.c b/src/libcharon/plugins/eap_radius/eap_radius_xauth.c
index d00f6bb..0fea509 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_xauth.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_xauth.c
@@ -87,12 +87,12 @@ static bool build_round(private_eap_radius_xauth_t *this, cp_payload_t *cp)
 		return FALSE;
 	}
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-					CONFIGURATION_ATTRIBUTE_V1, this->round.type, chunk_empty));
+					PLV1_CONFIGURATION_ATTRIBUTE, this->round.type, chunk_empty));
 
 	if (this->round.message && strlen(this->round.message))
 	{
 		cp->add_attribute(cp, configuration_attribute_create_chunk(
-					CONFIGURATION_ATTRIBUTE_V1, XAUTH_MESSAGE,
+					PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_MESSAGE,
 					chunk_from_str(this->round.message)));
 	}
 	return TRUE;
@@ -103,10 +103,10 @@ METHOD(xauth_method_t, initiate, status_t,
 {
 	cp_payload_t *cp;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
 	/* first message always comes with username */
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-				CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+				PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
 
 	if (build_round(this, cp))
 	{
@@ -211,7 +211,7 @@ METHOD(xauth_method_t, process, status_t,
 	{
 		return verify_radius(this);
 	}
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
 	if (build_round(this, cp))
 	{
 		*out = cp;
diff --git a/src/libcharon/plugins/eap_sim/Makefile.am b/src/libcharon/plugins/eap_sim/Makefile.am
index 2e9dad1..f681385 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.am
+++ b/src/libcharon/plugins/eap_sim/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-sim.la
diff --git a/src/libcharon/plugins/eap_sim/Makefile.in b/src/libcharon/plugins/eap_sim/Makefile.in
index 10b881f..494efd9 100644
--- a/src/libcharon/plugins/eap_sim/Makefile.in
+++ b/src/libcharon/plugins/eap_sim/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-sim.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-sim.la
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.am b/src/libcharon/plugins/eap_sim_file/Makefile.am
index 0d4da07..c38e55e 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.am
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la
diff --git a/src/libcharon/plugins/eap_sim_file/Makefile.in b/src/libcharon/plugins/eap_sim_file/Makefile.in
index e4552d1..82e7561 100644
--- a/src/libcharon/plugins/eap_sim_file/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_file/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-sim-file.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-sim-file.la
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
index e5e9d01..2292204 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${pcsclite_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version
 libstrongswan_eap_sim_pcsc_la_LIBADD  = ${pcsclite_LIBS}
diff --git a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
index 628f537..9a7a190 100644
--- a/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
+++ b/src/libcharon/plugins/eap_sim_pcsc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ 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@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -423,7 +427,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${pcsclite_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version
 libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS} \
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
index 0f21c68..f40efbd 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
diff --git a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
index 4a8127f..886b0c5 100644
--- a/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_pseudonym/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ 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@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-simaka-pseudonym.la
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
index be000c6..0fb6222 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
diff --git a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
index 8ac480d..57c6424 100644
--- a/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_reauth/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libsimaka
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-simaka-reauth.la
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
index 9a52bd8..b7d6fd4 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.am
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.in b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
index 79b45a9..eb4d3fa 100644
--- a/src/libcharon/plugins/eap_simaka_sql/Makefile.in
+++ b/src/libcharon/plugins/eap_simaka_sql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
diff --git a/src/libcharon/plugins/eap_tls/Makefile.am b/src/libcharon/plugins/eap_tls/Makefile.am
index c4944fc..825beb8 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.am
+++ b/src/libcharon/plugins/eap_tls/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-tls.la
diff --git a/src/libcharon/plugins/eap_tls/Makefile.in b/src/libcharon/plugins/eap_tls/Makefile.in
index c2b8b4f..c63d56b 100644
--- a/src/libcharon/plugins/eap_tls/Makefile.in
+++ b/src/libcharon/plugins/eap_tls/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-tls.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-tls.la
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.am b/src/libcharon/plugins/eap_tnc/Makefile.am
index 9586bef..6fc78bc 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.am
+++ b/src/libcharon/plugins/eap_tnc/Makefile.am
@@ -7,7 +7,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-tnc.la
diff --git a/src/libcharon/plugins/eap_tnc/Makefile.in b/src/libcharon/plugins/eap_tnc/Makefile.in
index 1f2ace2..97552df 100644
--- a/src/libcharon/plugins/eap_tnc/Makefile.in
+++ b/src/libcharon/plugins/eap_tnc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-tnc.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-tnc.la
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c
index 2147c04..62d23d0 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c
@@ -47,6 +47,11 @@ struct private_eap_tnc_t {
 	eap_tnc_t public;
 
 	/**
+	 * Inner EAP authentication type
+	 */
+	eap_type_t type;
+
+	/**
 	 * Outer EAP authentication type
 	 */
 	eap_type_t auth_type;
@@ -124,7 +129,7 @@ METHOD(eap_method_t, initiate, status_t,
 	private_eap_tnc_t *this, eap_payload_t **out)
 {
 	chunk_t data;
-	u_int32_t auth_type;
+	uint32_t auth_type;
 
 	/* Determine TNC Client Authentication Type */
 	switch (this->auth_type)
@@ -175,10 +180,10 @@ METHOD(eap_method_t, process, status_t,
 }
 
 METHOD(eap_method_t, get_type, eap_type_t,
-	private_eap_tnc_t *this, u_int32_t *vendor)
+	private_eap_tnc_t *this, uint32_t *vendor)
 {
 	*vendor = 0;
-	return EAP_TNC;
+	return this->type;
 }
 
 METHOD(eap_method_t, get_msk, status_t,
@@ -192,14 +197,14 @@ METHOD(eap_method_t, get_msk, status_t,
 	return FAILED;
 }
 
-METHOD(eap_method_t, get_identifier, u_int8_t,
+METHOD(eap_method_t, get_identifier, uint8_t,
 	private_eap_tnc_t *this)
 {
 	return this->tls_eap->get_identifier(this->tls_eap);
 }
 
 METHOD(eap_method_t, set_identifier, void,
-	private_eap_tnc_t *this, u_int8_t identifier)
+	private_eap_tnc_t *this, uint8_t identifier)
 {
 	this->tls_eap->set_identifier(this->tls_eap, identifier);
 }
@@ -214,7 +219,7 @@ METHOD(eap_method_t, destroy, void,
 	private_eap_tnc_t *this)
 {
 	chunk_t pdp_server;
-	u_int16_t pdp_port;
+	uint16_t pdp_port;
 	tls_t *tls;
 
 	pdp_server = this->tnccs->get_pdp_server(this->tnccs, &pdp_port);
@@ -245,13 +250,14 @@ METHOD(eap_inner_method_t, set_auth_type, void,
  * Generic private constructor
  */
 static eap_tnc_t *eap_tnc_create(identification_t *server,
-								 identification_t *peer, bool is_server)
+								 identification_t *peer, bool is_server,
+								 eap_type_t type)
 {
 	private_eap_tnc_t *this;
 	int max_msg_count;
 	char* protocol;
 	tnccs_t *tnccs;
-	tnccs_type_t type;
+	tnccs_type_t tnccs_type;
 
 	INIT(this,
 		.public = {
@@ -270,24 +276,25 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
 				.set_auth_type = _set_auth_type,
 			},
 		},
+		.type = type,
 	);
 
 	max_msg_count = lib->settings->get_int(lib->settings,
 						"%s.plugins.eap-tnc.max_message_count",
 						EAP_TNC_MAX_MESSAGE_COUNT, lib->ns);
 	protocol = lib->settings->get_str(lib->settings,
-						"%s.plugins.eap-tnc.protocol", "tnccs-1.1", lib->ns);
+						"%s.plugins.eap-tnc.protocol", "tnccs-2.0", lib->ns);
 	if (strcaseeq(protocol, "tnccs-2.0"))
 	{
-		type = TNCCS_2_0;
+		tnccs_type = TNCCS_2_0;
 	}
 	else if (strcaseeq(protocol, "tnccs-1.1"))
 	{
-		type = TNCCS_1_1;
+		tnccs_type = TNCCS_1_1;
 	}
 	else if (strcaseeq(protocol, "tnccs-dynamic") && is_server)
 	{
-		type = TNCCS_DYNAMIC;
+		tnccs_type = TNCCS_DYNAMIC;
 	}
 	else
 	{
@@ -295,8 +302,9 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
 		free(this);
 		return NULL;
 	}
-	tnccs = tnc->tnccs->create_instance(tnc->tnccs, type,
-						is_server, server, peer, TNC_IFT_EAP_1_1,
+	tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type,
+						is_server, server, peer,
+						(type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0,
 						is_server ? enforce_recommendation : NULL);
 	if (!tnccs)
 	{
@@ -305,7 +313,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
 		return NULL;
 	}
 	this->tnccs = tnccs->get_ref(tnccs);
-	this->tls_eap = tls_eap_create(EAP_TNC, &tnccs->tls,
+	this->tls_eap = tls_eap_create(type, &tnccs->tls,
 								   EAP_TNC_MAX_MESSAGE_LEN,
 								   max_msg_count, FALSE);
 	if (!this->tls_eap)
@@ -319,11 +327,23 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
 eap_tnc_t *eap_tnc_create_server(identification_t *server,
 								 identification_t *peer)
 {
-	return eap_tnc_create(server, peer, TRUE);
+	return eap_tnc_create(server, peer, TRUE, EAP_TNC);
 }
 
 eap_tnc_t *eap_tnc_create_peer(identification_t *server,
 							   identification_t *peer)
 {
-	return eap_tnc_create(server, peer, FALSE);
+	return eap_tnc_create(server, peer, FALSE, EAP_TNC);
+}
+
+eap_tnc_t *eap_tnc_pt_create_server(identification_t *server,
+								 identification_t *peer)
+{
+	return eap_tnc_create(server, peer, TRUE, EAP_PT_EAP);
+}
+
+eap_tnc_t *eap_tnc_pt_create_peer(identification_t *server,
+							   identification_t *peer)
+{
+	return eap_tnc_create(server, peer, FALSE, EAP_PT_EAP);
 }
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.h b/src/libcharon/plugins/eap_tnc/eap_tnc.h
index 8c881f6..d7ea9f4 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.h
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.h
@@ -26,7 +26,7 @@ typedef struct eap_tnc_t eap_tnc_t;
 #include <sa/eap/eap_inner_method.h>
 
 /**
- * Implementation of the eap_method_t interface using EAP-TNC.
+ * Implementation of the eap_method_t interface using EAP-TNC or PT-EAP.
  */
 struct eap_tnc_t {
 
@@ -43,7 +43,8 @@ struct eap_tnc_t {
  * @param peer		ID of the EAP client
  * @return			eap_tnc_t object
  */
-eap_tnc_t *eap_tnc_create_server(identification_t *server, identification_t *peer);
+eap_tnc_t *eap_tnc_create_server(identification_t *server,
+								 identification_t *peer);
 
 /**
  * Creates the EAP method EAP-TNC acting as peer.
@@ -52,6 +53,27 @@ eap_tnc_t *eap_tnc_create_server(identification_t *server, identification_t *pee
  * @param peer		ID of the EAP client
  * @return			eap_tnc_t object
  */
-eap_tnc_t *eap_tnc_create_peer(identification_t *server, identification_t *peer);
+eap_tnc_t *eap_tnc_create_peer(identification_t *server,
+							   identification_t *peer);
+
+/**
+ * Creates the EAP method PT-EAP acting as server.
+ *
+ * @param server	ID of the EAP server
+ * @param peer		ID of the EAP client
+ * @return			eap_tnc_t object
+ */
+eap_tnc_t *eap_tnc_pt_create_server(identification_t *server,
+									identification_t *peer);
+
+/**
+ * Creates the EAP method PT-EAP acting as peer.
+ *
+ * @param server	ID of the EAP server
+ * @param peer		ID of the EAP client
+ * @return			eap_tnc_t object
+ */
+eap_tnc_t *eap_tnc_pt_create_peer(identification_t *server,
+								  identification_t *peer);
 
 #endif /** EAP_TNC_H_ @}*/
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c
index 813a75f..d0f79fa 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc_plugin.c
@@ -36,6 +36,14 @@ METHOD(plugin_t, get_features, int,
 			PLUGIN_PROVIDE(EAP_PEER, EAP_TNC),
 				PLUGIN_DEPENDS(EAP_PEER, EAP_TTLS),
 				PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+		PLUGIN_CALLBACK(eap_method_register, eap_tnc_pt_create_server),
+			PLUGIN_PROVIDE(EAP_SERVER, EAP_PT_EAP),
+				PLUGIN_DEPENDS(EAP_SERVER, EAP_TTLS),
+				PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
+		PLUGIN_CALLBACK(eap_method_register, eap_tnc_pt_create_peer),
+			PLUGIN_PROVIDE(EAP_PEER, EAP_PT_EAP),
+				PLUGIN_DEPENDS(EAP_PEER, EAP_TTLS),
+				PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
 	};
 	*features = f;
 	return countof(f);
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.am b/src/libcharon/plugins/eap_ttls/Makefile.am
index 81776d8..3a7a8cd 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.am
+++ b/src/libcharon/plugins/eap_ttls/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libradius
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-eap-ttls.la
diff --git a/src/libcharon/plugins/eap_ttls/Makefile.in b/src/libcharon/plugins/eap_ttls/Makefile.in
index b693787..70cc184 100644
--- a/src/libcharon/plugins/eap_ttls/Makefile.in
+++ b/src/libcharon/plugins/eap_ttls/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libradius
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-eap-ttls.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-eap-ttls.la
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
index 88c2b88..9d145ea 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2010 Andreas Steffen
- * Copyright (C) 2010 HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2010-2014 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
@@ -107,22 +107,34 @@ static status_t start_phase2_auth(private_eap_ttls_server_t *this)
 }
 
 /**
- * If configured, start EAP-TNC protocol
+ * If configured, start PT-EAP or legacy EAP-TNC protocol
  */
 static status_t start_phase2_tnc(private_eap_ttls_server_t *this,
 								 eap_type_t auth_type)
 {
 	eap_inner_method_t *inner_method;
+	eap_type_t type;
+	char *eap_type_str;
 
 	if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings,
 							"%s.plugins.eap-ttls.phase2_tnc", FALSE, lib->ns))
 	{
-		DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, EAP_TNC);
-		this->method = charon->eap->create_instance(charon->eap, EAP_TNC,
+		eap_type_str = lib->settings->get_str(lib->settings,
+							"%s.plugins.eap-ttls.phase2_tnc_method", "pt",
+							lib->ns);
+		type = eap_type_from_string(eap_type_str);
+		if (type == 0)
+		{
+			DBG1(DBG_IKE, "unrecognized phase2 EAP TNC method \"%s\"",
+						   eap_type_str);
+			return FAILED;
+		}
+		DBG1(DBG_IKE, "phase2 method %N selected", eap_type_names, type);
+		this->method = charon->eap->create_instance(charon->eap, type,
 									0, EAP_SERVER, this->server, this->peer);
 		if (this->method == NULL)
 		{
-			DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_TNC);
+			DBG1(DBG_IKE, "%N method not available", eap_type_names, type);
 			return FAILED;
 		}
 		inner_method = (eap_inner_method_t *)this->method;
@@ -135,7 +147,7 @@ static status_t start_phase2_tnc(private_eap_ttls_server_t *this,
 		}
 		else
 		{
-			DBG1(DBG_IKE, "%N method failed", eap_type_names, EAP_TNC);
+			DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
 			return FAILED;
 		}
 	}
@@ -151,7 +163,7 @@ METHOD(tls_application_t, process, status_t,
 	eap_payload_t *in;
 	eap_code_t code;
 	eap_type_t type = EAP_NAK, received_type;
-	u_int32_t vendor, received_vendor;
+	uint32_t vendor, received_vendor;
 
 	status = this->avp->process(this->avp, reader, &data);
 	switch (status)
@@ -297,7 +309,7 @@ METHOD(tls_application_t, build, status_t,
 	chunk_t data;
 	eap_code_t code;
 	eap_type_t type;
-	u_int32_t vendor;
+	uint32_t vendor;
 
 	if (this->method == NULL && this->start_phase2 &&
 		lib->settings->get_bool(lib->settings,
diff --git a/src/libcharon/plugins/error_notify/Makefile.am b/src/libcharon/plugins/error_notify/Makefile.am
index 980fe1f..1c64bd2 100644
--- a/src/libcharon/plugins/error_notify/Makefile.am
+++ b/src/libcharon/plugins/error_notify/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-error-notify.la
diff --git a/src/libcharon/plugins/error_notify/Makefile.in b/src/libcharon/plugins/error_notify/Makefile.in
index 8dd7875..0782dde 100644
--- a/src/libcharon/plugins/error_notify/Makefile.in
+++ b/src/libcharon/plugins/error_notify/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -274,6 +274,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -292,6 +293,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -319,6 +321,7 @@ 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@
@@ -410,6 +413,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -427,7 +431,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-error-notify.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-error-notify.la
diff --git a/src/libcharon/plugins/farp/Makefile.am b/src/libcharon/plugins/farp/Makefile.am
index 95e57d8..0d862b0 100644
--- a/src/libcharon/plugins/farp/Makefile.am
+++ b/src/libcharon/plugins/farp/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-farp.la
diff --git a/src/libcharon/plugins/farp/Makefile.in b/src/libcharon/plugins/farp/Makefile.in
index 13f0e52..75ff158 100644
--- a/src/libcharon/plugins/farp/Makefile.in
+++ b/src/libcharon/plugins/farp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-farp.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-farp.la
diff --git a/src/libcharon/plugins/ha/Makefile.am b/src/libcharon/plugins/ha/Makefile.am
index c10f7f9..50d3423 100644
--- a/src/libcharon/plugins/ha/Makefile.am
+++ b/src/libcharon/plugins/ha/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-ha.la
diff --git a/src/libcharon/plugins/ha/Makefile.in b/src/libcharon/plugins/ha/Makefile.in
index d7a77ee..cec7362 100644
--- a/src/libcharon/plugins/ha/Makefile.in
+++ b/src/libcharon/plugins/ha/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-ha.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-ha.la
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 1ce9d3a..6ff24c3 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -245,13 +245,8 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
 		{
 			if (old_sa)
 			{
-				peer_cfg_t *peer_cfg = old_sa->get_peer_cfg(old_sa);
-
-				if (peer_cfg)
-				{
-					ike_sa->set_peer_cfg(ike_sa, peer_cfg);
-					ike_sa->inherit(ike_sa, old_sa);
-				}
+				ike_sa->inherit_pre(ike_sa, old_sa);
+				ike_sa->inherit_post(ike_sa, old_sa);
 				charon->ike_sa_manager->checkin_and_destroy(
 												charon->ike_sa_manager, old_sa);
 				old_sa = NULL;
@@ -1077,4 +1072,3 @@ ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index 74147e5..dd23993 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -207,6 +207,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
 							 charon->socket->get_port(charon->socket, FALSE),
 							 remote, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
 	ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+	ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 	peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND,
 						UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE,
 						TRUE, 30, 0, FALSE, NULL, NULL);
@@ -235,6 +236,7 @@ static void setup_tunnel(private_ha_tunnel_t *this,
 	ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
 	child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
 	child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+	child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
 	peer_cfg->add_child_cfg(peer_cfg, child_cfg);
 
 	this->backend.cfg = peer_cfg;
diff --git a/src/libcharon/plugins/ipseckey/Makefile.am b/src/libcharon/plugins/ipseckey/Makefile.am
index 3a69e52..aed63c1 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.am
+++ b/src/libcharon/plugins/ipseckey/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-ipseckey.la
diff --git a/src/libcharon/plugins/ipseckey/Makefile.in b/src/libcharon/plugins/ipseckey/Makefile.in
index 1f62f40..da2e8d7 100644
--- a/src/libcharon/plugins/ipseckey/Makefile.in
+++ b/src/libcharon/plugins/ipseckey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-ipseckey.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-ipseckey.la
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.am b/src/libcharon/plugins/kernel_iph/Makefile.am
new file mode 100644
index 0000000..56946ae
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/Makefile.am
@@ -0,0 +1,20 @@
+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-kernel-iph.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-iph.la
+endif
+
+libstrongswan_kernel_iph_la_SOURCES = \
+	kernel_iph_plugin.h kernel_iph_plugin.c \
+	kernel_iph_net.h kernel_iph_net.c
+
+libstrongswan_kernel_iph_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_iph_la_LIBADD = -liphlpapi
diff --git a/src/libcharon/plugins/kernel_iph/Makefile.in b/src/libcharon/plugins/kernel_iph/Makefile.in
new file mode 100644
index 0000000..460c7b7
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/Makefile.in
@@ -0,0 +1,768 @@
+# 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_iph
+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_iph_la_DEPENDENCIES =
+am_libstrongswan_kernel_iph_la_OBJECTS = kernel_iph_plugin.lo \
+	kernel_iph_net.lo
+libstrongswan_kernel_iph_la_OBJECTS =  \
+	$(am_libstrongswan_kernel_iph_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_iph_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_kernel_iph_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_kernel_iph_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_kernel_iph_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_iph_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_iph_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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-kernel-iph.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-iph.la
+libstrongswan_kernel_iph_la_SOURCES = \
+	kernel_iph_plugin.h kernel_iph_plugin.c \
+	kernel_iph_net.h kernel_iph_net.c
+
+libstrongswan_kernel_iph_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_iph_la_LIBADD = -liphlpapi
+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_iph/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_iph/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-iph.la: $(libstrongswan_kernel_iph_la_OBJECTS) $(libstrongswan_kernel_iph_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_iph_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_kernel_iph_la_LINK) $(am_libstrongswan_kernel_iph_la_rpath) $(libstrongswan_kernel_iph_la_OBJECTS) $(libstrongswan_kernel_iph_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_iph_net.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_iph_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_iph/kernel_iph_net.c b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
new file mode 100644
index 0000000..a4be404
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
@@ -0,0 +1,775 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/* Windows 7, for some iphlpapi.h functionality */
+#define _WIN32_WINNT 0x0601
+#include <winsock2.h>
+#include <ws2ipdef.h>
+#include <windows.h>
+#include <ntddndis.h>
+#include <naptypes.h>
+#include <iphlpapi.h>
+
+#include "kernel_iph_net.h"
+
+#include <hydra.h>
+#include <threading/mutex.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+
+/** delay before firing roam events (ms) */
+#define ROAM_DELAY 500
+
+typedef struct private_kernel_iph_net_t private_kernel_iph_net_t;
+
+/**
+ * Private data of kernel_iph_net implementation.
+ */
+struct private_kernel_iph_net_t {
+
+	/**
+	 * Public interface.
+	 */
+	kernel_iph_net_t public;
+
+	/**
+	 * NotifyIpInterfaceChange() handle
+	 */
+	HANDLE changes;
+
+	/**
+	 * EnableRouter() OVERLAPPED
+	 */
+	OVERLAPPED router;
+
+	/**
+	 * Mutex to access interface list
+	 */
+	mutex_t *mutex;
+
+	/**
+	 * Known interfaces, as iface_t
+	 */
+	linked_list_t *ifaces;
+
+	/**
+	 * Earliest time of the next roam event
+	 */
+	timeval_t roam_next;
+
+	/**
+	 * Roam event due to address change?
+	 */
+	bool roam_address;
+};
+
+/**
+ * Interface entry
+ */
+typedef struct  {
+	/** interface index */
+	DWORD ifindex;
+	/** interface name */
+	char *ifname;
+	/** interface description */
+	char *ifdesc;
+	/** type of interface */
+	DWORD iftype;
+	/** interface status */
+	IF_OPER_STATUS status;
+	/** list of known addresses, as host_t */
+	linked_list_t *addrs;
+} iface_t;
+
+/**
+ * Clean up an iface_t
+ */
+static void iface_destroy(iface_t *this)
+{
+	this->addrs->destroy_offset(this->addrs, offsetof(host_t, destroy));
+	free(this->ifname);
+	free(this->ifdesc);
+	free(this);
+}
+
+/**
+ * Enum names for Windows IF_OPER_STATUS
+ */
+ENUM(if_oper_names, IfOperStatusUp, IfOperStatusLowerLayerDown,
+	"Up",
+	"Down",
+	"Testing",
+	"Unknown",
+	"Dormant",
+	"NotPresent",
+	"LowerLayerDown",
+);
+
+/**
+ * Callback function that raises the delayed roam event
+ */
+static job_requeue_t roam_event(private_kernel_iph_net_t *this)
+{
+	bool address;
+
+	this->mutex->lock(this->mutex);
+	address = this->roam_address;
+	this->roam_address = FALSE;
+	this->mutex->unlock(this->mutex);
+
+	hydra->kernel_interface->roam(hydra->kernel_interface, address);
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Fire delayed roam event, caller should hold mutex
+ */
+static void fire_roam_event(private_kernel_iph_net_t *this, bool address)
+{
+	timeval_t now;
+
+	time_monotonic(&now);
+	this->roam_address |= address;
+	if (timercmp(&now, &this->roam_next, >))
+	{
+		timeval_add_ms(&now, ROAM_DELAY);
+		this->roam_next = now;
+		lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
+							callback_job_create((callback_job_cb_t)roam_event,
+												this, NULL, NULL),
+							ROAM_DELAY);
+	}
+}
+
+/**
+ * Update addresses for an iface entry
+ */
+static void update_addrs(private_kernel_iph_net_t *this, iface_t *entry,
+						 IP_ADAPTER_ADDRESSES *addr, bool log)
+{
+	IP_ADAPTER_UNICAST_ADDRESS *current;
+	enumerator_t *enumerator;
+	linked_list_t *list;
+	host_t *host, *old;
+	bool changes = FALSE;
+
+	list = entry->addrs;
+	entry->addrs = linked_list_create();
+
+	for (current = addr->FirstUnicastAddress; current; current = current->Next)
+	{
+		if (current->Address.lpSockaddr->sa_family == AF_INET6)
+		{
+			struct sockaddr_in6 *sin;
+
+			sin = (struct sockaddr_in6*)current->Address.lpSockaddr;
+			if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
+			{
+				continue;
+			}
+		}
+
+		host = host_create_from_sockaddr(current->Address.lpSockaddr);
+		if (host)
+		{
+			bool found = FALSE;
+
+			enumerator = list->create_enumerator(list);
+			while (enumerator->enumerate(enumerator, &old))
+			{
+				if (host->ip_equals(host, old))
+				{
+					list->remove_at(list, enumerator);
+					old->destroy(old);
+					found = TRUE;
+				}
+			}
+			enumerator->destroy(enumerator);
+
+			entry->addrs->insert_last(entry->addrs, host);
+
+			if (!found && log)
+			{
+				DBG1(DBG_KNL, "%H appeared on interface %u '%s'",
+					 host, entry->ifindex, entry->ifdesc);
+				changes = TRUE;
+			}
+		}
+	}
+
+	while (list->remove_first(list, (void**)&old) == SUCCESS)
+	{
+		if (log)
+		{
+			DBG1(DBG_KNL, "%H disappeared from interface %u '%s'",
+				 old, entry->ifindex, entry->ifdesc);
+			changes = TRUE;
+		}
+		old->destroy(old);
+	}
+	list->destroy(list);
+
+	if (changes)
+	{
+		fire_roam_event(this, TRUE);
+	}
+}
+
+/**
+ * Add an interface entry
+ */
+static void add_interface(private_kernel_iph_net_t *this,
+						  IP_ADAPTER_ADDRESSES *addr, bool log)
+{
+	enumerator_t *enumerator;
+	iface_t *entry;
+	bool exists = FALSE;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->ifaces->create_enumerator(this->ifaces);
+	while (enumerator->enumerate(enumerator, &entry))
+	{
+		if (entry->ifindex == addr->IfIndex)
+		{
+			exists = TRUE;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+
+	if (!exists)
+	{
+		char desc[128] = "";
+
+		wcstombs(desc, addr->Description, sizeof(desc));
+
+		INIT(entry,
+			.ifindex = addr->IfIndex,
+			.ifname = strdup(addr->AdapterName),
+			.ifdesc = strdup(desc),
+			.iftype = addr->IfType,
+			.status = addr->OperStatus,
+			.addrs = linked_list_create(),
+		);
+
+		if (log)
+		{
+			DBG1(DBG_KNL, "interface %u '%s' appeared",
+				 entry->ifindex, entry->ifdesc);
+		}
+
+		this->mutex->lock(this->mutex);
+		update_addrs(this, entry, addr, log);
+		this->ifaces->insert_last(this->ifaces, entry);
+		this->mutex->unlock(this->mutex);
+	}
+}
+
+/**
+ * Remove an interface entry that is gone
+ */
+static void remove_interface(private_kernel_iph_net_t *this, NET_IFINDEX index)
+{
+	enumerator_t *enumerator;
+	iface_t *entry;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->ifaces->create_enumerator(this->ifaces);
+	while (enumerator->enumerate(enumerator, &entry))
+	{
+		if (entry->ifindex == index)
+		{
+			this->ifaces->remove_at(this->ifaces, enumerator);
+			DBG1(DBG_KNL, "interface %u '%s' disappeared",
+				 entry->ifindex, entry->ifdesc);
+			iface_destroy(entry);
+			fire_roam_event(this, TRUE);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Update an interface entry changed
+ */
+static void update_interface(private_kernel_iph_net_t *this,
+							 IP_ADAPTER_ADDRESSES *addr)
+{
+	enumerator_t *enumerator;
+	iface_t *entry;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->ifaces->create_enumerator(this->ifaces);
+	while (enumerator->enumerate(enumerator, &entry))
+	{
+		if (entry->ifindex == addr->IfIndex)
+		{
+			if (entry->status != addr->OperStatus)
+			{
+				DBG1(DBG_KNL, "interface %u '%s' changed state from %N to %N",
+					 entry->ifindex, entry->ifdesc, if_oper_names,
+					 entry->status, if_oper_names, addr->OperStatus);
+				entry->status = addr->OperStatus;
+				fire_roam_event(this, TRUE);
+			}
+			update_addrs(this, entry, addr, TRUE);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+/**
+ * MinGW gets MIB_IPINTERFACE_ROW wrong, as it packs InterfaceLuid just after
+ * Family. Fix that with our own version of the struct header.
+ */
+typedef struct {
+	ADDRESS_FAMILY Family;
+	union {
+		ULONG64 Value;
+		struct {
+			ULONG64 Reserved :24;
+			ULONG64 NetLuidIndex :24;
+			ULONG64 IfType :16;
+		} Info;
+	} InterfaceLuid;
+	NET_IFINDEX InterfaceIndex;
+	/* more would go here if needed */
+} MIB_IPINTERFACE_ROW_FIXUP;
+
+/**
+ * NotifyIpInterfaceChange() callback
+ */
+static void WINAPI change_interface(void *user, PMIB_IPINTERFACE_ROW row_badal,
+									MIB_NOTIFICATION_TYPE type)
+{
+	private_kernel_iph_net_t *this = user;
+	MIB_IPINTERFACE_ROW_FIXUP* row = (MIB_IPINTERFACE_ROW_FIXUP*)row_badal;
+	IP_ADAPTER_ADDRESSES addrs[64], *current;
+	ULONG res, size = sizeof(addrs);
+
+	if (row && type == MibDeleteInstance)
+	{
+		remove_interface(this, row->InterfaceIndex);
+	}
+	else
+	{
+		res = GetAdaptersAddresses(AF_UNSPEC,
+						GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
+						GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME,
+						NULL, addrs, &size);
+		if (res == NO_ERROR)
+		{
+			current = addrs;
+			while (current)
+			{
+				/* row is NULL only on MibInitialNotification */
+				if (!row || row->InterfaceIndex == current->IfIndex)
+				{
+					switch (type)
+					{
+						case MibParameterNotification:
+							update_interface(this, current);
+							break;
+						case MibInitialNotification:
+							add_interface(this, current, FALSE);
+							break;
+						case MibAddInstance:
+							add_interface(this, current, TRUE);
+							break;
+						default:
+							break;
+					}
+				}
+				current = current->Next;
+			}
+		}
+		else
+		{
+			DBG1(DBG_KNL, "getting IPH adapter addresses failed: 0x%08lx", res);
+		}
+	}
+}
+
+/**
+ * Get an iface entry for a local address, does no locking
+ */
+static iface_t* address2entry(private_kernel_iph_net_t *this, host_t *ip)
+{
+	enumerator_t *ifaces, *addrs;
+	iface_t *entry, *found = NULL;
+	host_t *host;
+
+	ifaces = this->ifaces->create_enumerator(this->ifaces);
+	while (!found && ifaces->enumerate(ifaces, &entry))
+	{
+		addrs = entry->addrs->create_enumerator(entry->addrs);
+		while (!found && addrs->enumerate(addrs, &host))
+		{
+			if (host->ip_equals(host, ip))
+			{
+				found = entry;
+			}
+		}
+		addrs->destroy(addrs);
+	}
+	ifaces->destroy(ifaces);
+
+	return found;
+}
+
+METHOD(kernel_net_t, get_interface_name, bool,
+	private_kernel_iph_net_t *this, host_t* ip, char **name)
+{
+	iface_t *entry;
+
+	this->mutex->lock(this->mutex);
+	entry = address2entry(this, ip);
+	if (entry && name)
+	{
+		*name = strdup(entry->ifname);
+	}
+	this->mutex->unlock(this->mutex);
+
+	return entry != NULL;
+}
+
+/**
+ * Address enumerator
+ */
+typedef struct {
+	/** implements enumerator_t */
+	enumerator_t public;
+	/** what kind of address should we enumerate? */
+	kernel_address_type_t which;
+	/** enumerator over interfaces */
+	enumerator_t *ifaces;
+	/** current enumerator over addresses, or NULL */
+	enumerator_t *addrs;
+	/** mutex to unlock on destruction */
+	mutex_t *mutex;
+} addr_enumerator_t;
+
+METHOD(enumerator_t, addr_enumerate, bool,
+	addr_enumerator_t *this, host_t **host)
+{
+	iface_t *entry;
+
+	while (TRUE)
+	{
+		while (!this->addrs)
+		{
+			if (!this->ifaces->enumerate(this->ifaces, &entry))
+			{
+				return FALSE;
+			}
+			if (entry->iftype == IF_TYPE_SOFTWARE_LOOPBACK &&
+				!(this->which & ADDR_TYPE_LOOPBACK))
+			{
+				continue;
+			}
+			if (entry->status != IfOperStatusUp &&
+				!(this->which & ADDR_TYPE_DOWN))
+			{
+				continue;
+			}
+			this->addrs = entry->addrs->create_enumerator(entry->addrs);
+		}
+		if (this->addrs->enumerate(this->addrs, host))
+		{
+			return TRUE;
+		}
+		this->addrs->destroy(this->addrs);
+		this->addrs = NULL;
+	}
+}
+
+METHOD(enumerator_t, addr_destroy, void,
+	addr_enumerator_t *this)
+{
+	DESTROY_IF(this->addrs);
+	this->ifaces->destroy(this->ifaces);
+	this->mutex->unlock(this->mutex);
+	free(this);
+}
+
+METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
+	private_kernel_iph_net_t *this, kernel_address_type_t which)
+{
+	addr_enumerator_t *enumerator;
+
+	if (!(which & ADDR_TYPE_REGULAR))
+	{
+		/* we currently have no virtual, but regular IPs only */
+		return enumerator_create_empty();
+	}
+
+	this->mutex->lock(this->mutex);
+
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)_addr_enumerate,
+			.destroy = _addr_destroy,
+		},
+		.which = which,
+		.ifaces = this->ifaces->create_enumerator(this->ifaces),
+		.mutex = this->mutex,
+	);
+	return &enumerator->public;
+}
+
+METHOD(kernel_net_t, get_source_addr, host_t*,
+	private_kernel_iph_net_t *this, host_t *dest, host_t *src)
+{
+	MIB_IPFORWARD_ROW2 route;
+	SOCKADDR_INET best, *sai_dst, *sai_src = NULL;
+	DWORD res, index = 0;
+
+	res = GetBestInterfaceEx(dest->get_sockaddr(dest), &index);
+	if (res != NO_ERROR)
+	{
+		DBG1(DBG_KNL, "getting interface to %H failed: 0x%08x", dest, res);
+		return NULL;
+	}
+
+	sai_dst = (SOCKADDR_INET*)dest->get_sockaddr(dest);
+	if (src)
+	{
+		sai_src = (SOCKADDR_INET*)src->get_sockaddr(src);
+	}
+	res = GetBestRoute2(0, index, sai_src, sai_dst, 0, &route, &best);
+	if (res != NO_ERROR)
+	{
+		DBG2(DBG_KNL, "getting src address to %H failed: 0x%08x", dest, res);
+		return NULL;
+	}
+	return host_create_from_sockaddr((struct sockaddr*)&best);
+}
+
+METHOD(kernel_net_t, get_nexthop, host_t*,
+	private_kernel_iph_net_t *this, host_t *dest, int prefix, host_t *src)
+{
+	MIB_IPFORWARD_ROW2 route;
+	SOCKADDR_INET best, *sai_dst, *sai_src = NULL;
+	DWORD res, index = 0;
+	host_t *nexthop;
+
+	res = GetBestInterfaceEx(dest->get_sockaddr(dest), &index);
+	if (res != NO_ERROR)
+	{
+		DBG1(DBG_KNL, "getting interface to %H failed: 0x%08x", dest, res);
+		return NULL;
+	}
+
+	sai_dst = (SOCKADDR_INET*)dest->get_sockaddr(dest);
+	if (src)
+	{
+		sai_src = (SOCKADDR_INET*)src->get_sockaddr(src);
+	}
+	res = GetBestRoute2(0, index, sai_src, sai_dst, 0, &route, &best);
+	if (res != NO_ERROR)
+	{
+		DBG2(DBG_KNL, "getting nexthop to %H failed: 0x%08x", dest, res);
+		return NULL;
+	}
+	nexthop = host_create_from_sockaddr((struct sockaddr*)&route.NextHop);
+	if (nexthop)
+	{
+		if (!nexthop->is_anyaddr(nexthop))
+		{
+			return nexthop;
+		}
+		nexthop->destroy(nexthop);
+	}
+	return NULL;
+}
+
+METHOD(kernel_net_t, add_ip, status_t,
+	private_kernel_iph_net_t *this, host_t *virtual_ip, int prefix,
+	char *iface_name)
+{
+	return NOT_SUPPORTED;
+}
+
+METHOD(kernel_net_t, del_ip, status_t,
+	private_kernel_iph_net_t *this, host_t *virtual_ip, int prefix,
+	bool wait)
+{
+	return NOT_SUPPORTED;
+}
+
+/**
+ * Add or remove a route
+ */
+static status_t manage_route(private_kernel_iph_net_t *this, bool add,
+					chunk_t dst, u_int8_t prefixlen, host_t *gtw, char *name)
+{
+	MIB_IPFORWARD_ROW2 row = {
+		.DestinationPrefix = {
+			.PrefixLength = prefixlen,
+		},
+		.SitePrefixLength = prefixlen,
+		.ValidLifetime = INFINITE,
+		.PreferredLifetime = INFINITE,
+		.Metric = 10,
+		.Protocol = MIB_IPPROTO_NETMGMT,
+	};
+	enumerator_t *enumerator;
+	iface_t *entry;
+	ULONG ret;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->ifaces->create_enumerator(this->ifaces);
+	while (enumerator->enumerate(enumerator, &entry))
+	{
+		if (streq(name, entry->ifname))
+		{
+			row.InterfaceIndex = entry->ifindex;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+
+	if (!row.InterfaceIndex)
+	{
+		return NOT_FOUND;
+	}
+	switch (dst.len)
+	{
+		case 4:
+			row.DestinationPrefix.Prefix.si_family = AF_INET;
+			memcpy(&row.DestinationPrefix.Prefix.Ipv4.sin_addr,
+				   dst.ptr, dst.len);
+			break;
+		case 16:
+			row.DestinationPrefix.Prefix.si_family = AF_INET6;
+			memcpy(&row.DestinationPrefix.Prefix.Ipv6.sin6_addr,
+				   dst.ptr, dst.len);
+			break;
+		default:
+			return FAILED;
+	}
+	if (gtw)
+	{
+		memcpy(&row.NextHop, gtw->get_sockaddr(gtw),
+			   *gtw->get_sockaddr_len(gtw));
+	}
+
+	if (add)
+	{
+		ret = CreateIpForwardEntry2(&row);
+	}
+	else
+	{
+		ret = DeleteIpForwardEntry2(&row);
+	}
+	if (ret != NO_ERROR)
+	{
+		DBG1(DBG_KNL, "%sing route failed: 0x%08lx", add ? "add" : "remov", ret);
+		return FAILED;
+	}
+
+	if (add)
+	{
+		ret = EnableRouter(NULL, &this->router);
+		if (ret != ERROR_IO_PENDING)
+		{
+			DBG1(DBG_KNL, "EnableRouter router failed: 0x%08lx", ret);
+		}
+	}
+	else
+	{
+		ret = UnenableRouter(&this->router, NULL);
+		if (ret != NO_ERROR)
+		{
+			DBG1(DBG_KNL, "UnenableRouter router failed: 0x%08lx", ret);
+		}
+	}
+	return SUCCESS;
+}
+
+METHOD(kernel_net_t, add_route, status_t,
+	private_kernel_iph_net_t *this, chunk_t dst, u_int8_t prefixlen,
+	host_t *gateway, host_t *src, char *name)
+{
+	return manage_route(this, TRUE, dst, prefixlen, gateway, name);
+}
+
+METHOD(kernel_net_t, del_route, status_t,
+	private_kernel_iph_net_t *this, chunk_t dst, u_int8_t prefixlen,
+	host_t *gateway, host_t *src, char *name)
+{
+	return manage_route(this, FALSE, dst, prefixlen, gateway, name);
+}
+
+METHOD(kernel_net_t, destroy, void,
+	private_kernel_iph_net_t *this)
+{
+	if (this->changes)
+	{
+		CancelMibChangeNotify2(this->changes);
+	}
+	CloseHandle(this->router.hEvent);
+	this->mutex->destroy(this->mutex);
+	this->ifaces->destroy_function(this->ifaces, (void*)iface_destroy);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_iph_net_t *kernel_iph_net_create()
+{
+	private_kernel_iph_net_t *this;
+	ULONG res;
+
+	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,
+			},
+		},
+		.router = {
+			.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL),
+		},
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.ifaces = linked_list_create(),
+	);
+	/* PIPINTERFACE_CHANGE_CALLBACK is not using WINAPI in MinGW, which seems
+	 * to be wrong. Force a cast to our WINAPI call */
+	res = NotifyIpInterfaceChange(AF_UNSPEC, (void*)change_interface,
+								  this, TRUE, &this->changes);
+	if (res != NO_ERROR)
+	{
+		DBG1(DBG_KNL, "registering for IPH interface changes failed: 0x%08lx",
+			 res);
+		destroy(this);
+		return NULL;
+	}
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.h b/src/libcharon/plugins/kernel_iph/kernel_iph_net.h
new file mode 100644
index 0000000..c8f35de
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup kernel_iph_net_i kernel_iph_net
+ * @{ @ingroup kernel_iph
+ */
+
+#ifndef KERNEL_IPH_NET_H_
+#define KERNEL_IPH_NET_H_
+
+#include <kernel/kernel_net.h>
+
+typedef struct kernel_iph_net_t kernel_iph_net_t;
+
+/**
+ * Implementation of the kernel network interface using Windows IP Helper.
+ */
+struct kernel_iph_net_t {
+
+	/**
+	 * Implements kernel_net_t interface
+	 */
+	kernel_net_t interface;
+};
+
+/**
+ * Create IP Helper network backend instance.
+ *
+ * @return			kernel_iph_net_t instance
+ */
+kernel_iph_net_t *kernel_iph_net_create();
+
+#endif /** KERNEL_IPH_NET_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c
new file mode 100644
index 0000000..c5475e3
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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_iph_plugin.h"
+#include "kernel_iph_net.h"
+
+#include <hydra.h>
+
+typedef struct private_kernel_iph_plugin_t private_kernel_iph_plugin_t;
+
+/**
+ * Private data of kernel iph plugin
+ */
+struct private_kernel_iph_plugin_t {
+
+	/**
+	 * Implements plugin interface
+	 */
+	kernel_iph_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_kernel_iph_plugin_t *this)
+{
+	return "kernel-iph";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_kernel_iph_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK(kernel_net_register, kernel_iph_net_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_kernel_iph_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * See header file
+ */
+plugin_t *kernel_iph_plugin_create()
+{
+	private_kernel_iph_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_iph/kernel_iph_plugin.h b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.h
new file mode 100644
index 0000000..616f90e
--- /dev/null
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup kernel_iph kernel_iph
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_iph_plugin kernel_iph_plugin
+ * @{ @ingroup kernel_iph
+ */
+
+#ifndef KERNEL_IPH_PLUGIN_H_
+#define KERNEL_IPH_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct kernel_iph_plugin_t kernel_iph_plugin_t;
+
+/**
+ * Windows IP Helper API based networking backend.
+ */
+struct kernel_iph_plugin_t {
+
+	/**
+	 * Implements plugin interface.
+	 */
+	plugin_t plugin;
+};
+
+#endif /** KERNEL_IPH_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.am b/src/libcharon/plugins/kernel_libipsec/Makefile.am
index a39d067..eca2b23 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.am
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libipsec
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-kernel-libipsec.la
diff --git a/src/libcharon/plugins/kernel_libipsec/Makefile.in b/src/libcharon/plugins/kernel_libipsec/Makefile.in
index 3bc289d..a4e5ba9 100644
--- a/src/libcharon/plugins/kernel_libipsec/Makefile.in
+++ b/src/libcharon/plugins/kernel_libipsec/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libipsec
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-kernel-libipsec.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-kernel-libipsec.la
diff --git a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
index b335807..bd07a67 100644
--- a/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
+++ b/src/libcharon/plugins/kernel_libipsec/kernel_libipsec_ipsec.c
@@ -252,8 +252,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 	private_kernel_libipsec_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, bool initiator, bool encap, bool esn, bool inbound,
+	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,
 	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
 	return ipsec->sas->add_sa(ipsec->sas, src, dst, spi, protocol, reqid, mark,
@@ -313,7 +314,7 @@ static void add_exclude_route(private_kernel_libipsec_ipsec_t *this,
 	{
 		DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
 		gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
-												   dst, NULL);
+												   dst, -1, NULL);
 		if (gtw)
 		{
 			char *if_name = NULL;
@@ -444,7 +445,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, src);
+										hydra->kernel_interface, dst, -1, src);
 #endif
 
 	if (policy->route)
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.am b/src/libcharon/plugins/kernel_wfp/Makefile.am
new file mode 100644
index 0000000..85e5089
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.am
@@ -0,0 +1,33 @@
+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-kernel-wfp.la
+else
+plugin_LTLIBRARIES = libstrongswan-kernel-wfp.la
+endif
+
+libstrongswan_kernel_wfp_la_SOURCES = \
+	kernel_wfp_plugin.h kernel_wfp_plugin.c \
+	kernel_wfp_compat.c kernel_wfp_compat.h \
+	kernel_wfp_ipsec.h kernel_wfp_ipsec.c
+
+libstrongswan_kernel_wfp_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_wfp_la_LIBADD = -lfwpuclnt
+
+
+noinst_PROGRAMS = ipsecdump
+
+ipsecdump_SOURCES = \
+	ipsecdump.c
+ipsecdump_LDADD = \
+	libstrongswan-kernel-wfp.la \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la
+
+
+EXTRA_DIST = mingw-w64-4.8.1.diff
diff --git a/src/libcharon/plugins/kernel_wfp/Makefile.in b/src/libcharon/plugins/kernel_wfp/Makefile.in
new file mode 100644
index 0000000..ff987f8
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/Makefile.in
@@ -0,0 +1,801 @@
+# 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@
+noinst_PROGRAMS = ipsecdump$(EXEEXT)
+subdir = src/libcharon/plugins/kernel_wfp
+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_wfp_la_DEPENDENCIES =
+am_libstrongswan_kernel_wfp_la_OBJECTS = kernel_wfp_plugin.lo \
+	kernel_wfp_compat.lo kernel_wfp_ipsec.lo
+libstrongswan_kernel_wfp_la_OBJECTS =  \
+	$(am_libstrongswan_kernel_wfp_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_wfp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_kernel_wfp_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_kernel_wfp_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_kernel_wfp_la_rpath =
+PROGRAMS = $(noinst_PROGRAMS)
+am_ipsecdump_OBJECTS = ipsecdump.$(OBJEXT)
+ipsecdump_OBJECTS = $(am_ipsecdump_OBJECTS)
+ipsecdump_DEPENDENCIES = libstrongswan-kernel-wfp.la \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la
+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_wfp_la_SOURCES) $(ipsecdump_SOURCES)
+DIST_SOURCES = $(libstrongswan_kernel_wfp_la_SOURCES) \
+	$(ipsecdump_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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-kernel-wfp.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-wfp.la
+libstrongswan_kernel_wfp_la_SOURCES = \
+	kernel_wfp_plugin.h kernel_wfp_plugin.c \
+	kernel_wfp_compat.c kernel_wfp_compat.h \
+	kernel_wfp_ipsec.h kernel_wfp_ipsec.c
+
+libstrongswan_kernel_wfp_la_LDFLAGS = -module -avoid-version
+libstrongswan_kernel_wfp_la_LIBADD = -lfwpuclnt
+ipsecdump_SOURCES = \
+	ipsecdump.c
+
+ipsecdump_LDADD = \
+	libstrongswan-kernel-wfp.la \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la
+
+EXTRA_DIST = mingw-w64-4.8.1.diff
+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_wfp/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/kernel_wfp/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-wfp.la: $(libstrongswan_kernel_wfp_la_OBJECTS) $(libstrongswan_kernel_wfp_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_wfp_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_kernel_wfp_la_LINK) $(am_libstrongswan_kernel_wfp_la_rpath) $(libstrongswan_kernel_wfp_la_OBJECTS) $(libstrongswan_kernel_wfp_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_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
+
+ipsecdump$(EXEEXT): $(ipsecdump_OBJECTS) $(ipsecdump_DEPENDENCIES) $(EXTRA_ipsecdump_DEPENDENCIES) 
+	@rm -f ipsecdump$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(ipsecdump_OBJECTS) $(ipsecdump_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ipsecdump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_wfp_compat.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_wfp_ipsec.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_wfp_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) $(PROGRAMS)
+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-noinstPROGRAMS 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-noinstPROGRAMS \
+	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_wfp/ipsecdump.c b/src/libcharon/plugins/kernel_wfp/ipsecdump.c
new file mode 100644
index 0000000..7ca7df5
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/ipsecdump.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/* Windows 7, for some fwpmu.h functionality */
+#define _WIN32_WINNT 0x0601
+
+#include "kernel_wfp_compat.h"
+
+#include <library.h>
+
+ENUM(auth_type_names, IPSEC_AUTH_MD5, IPSEC_AUTH_AES_256,
+	"MD5",
+	"SHA1",
+	"SHA256",
+	"AES128",
+	"AES192",
+	"AES256",
+);
+
+ENUM(auth_config_names, 0, 5,
+	"HMAC96",
+	"HMAC96",
+	"HMAC128",
+	"GMAC",
+	"GMAC",
+	"GMAC",
+);
+
+ENUM(cipher_type_names, IPSEC_CIPHER_TYPE_DES, IPSEC_CIPHER_TYPE_AES_256,
+	"DES",
+	"3DES",
+	"AES128",
+	"AES192",
+	"AES256",
+);
+
+ENUM(cipher_config_names, 1, 8,
+	"CBC",
+	"CBC",
+	"CBC",
+	"CBC",
+	"CBC",
+	"GCM",
+	"GCM",
+	"GCM",
+);
+
+ENUM(match_type_names, FWP_MATCH_EQUAL, FWP_MATCH_NOT_EQUAL,
+	"equals",
+	"greater",
+	"less than",
+	"greater or equal than",
+	"less or equal than",
+	"in range",
+	"has all flags set",
+	"has any flags set",
+	"has none flags set",
+	"equals case insensitive",
+	"not equal",
+);
+
+ENUM(traffic_type_names, IPSEC_TRAFFIC_TYPE_TRANSPORT, IPSEC_TRAFFIC_TYPE_TUNNEL,
+	"Transport",
+	"Tunnel",
+);
+
+/**
+ * Print a GUID to a static buffer
+ */
+static char *guid2string(GUID *guid)
+{
+	static char buf[64];
+
+	snprintf(buf, sizeof(buf),
+		"%08x,%04x,%04x%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x",
+		guid->Data1, guid->Data2, guid->Data3,
+		guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+		guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+
+	return buf;
+}
+
+/**
+ * Convert filter condition key GUID to some known strings
+ */
+static char* cond2name(GUID *guid, bool *address)
+{
+	struct {
+		GUID guid;
+		char *name;
+		bool address;
+	} map[] = {
+		{ FWPM_CONDITION_IP_LOCAL_ADDRESS, "local address", TRUE},
+		{ FWPM_CONDITION_IP_REMOTE_ADDRESS, "remote address", TRUE},
+		{ FWPM_CONDITION_IP_SOURCE_ADDRESS, "source address", TRUE},
+		{ FWPM_CONDITION_IP_DESTINATION_ADDRESS, "destination address", TRUE},
+		{ FWPM_CONDITION_IP_LOCAL_PORT, "local port", FALSE},
+		{ FWPM_CONDITION_IP_REMOTE_PORT, "remote port", FALSE},
+		{ FWPM_CONDITION_IP_PROTOCOL, "protocol", FALSE},
+		{ FWPM_CONDITION_ICMP_CODE, "icmp code", FALSE},
+		{ FWPM_CONDITION_ICMP_TYPE, "icmp type", FALSE},
+	};
+	int i;
+
+	for (i = 0; i < countof(map); i++)
+	{
+		if (memeq(&map[i].guid, guid, sizeof(GUID)))
+		{
+			*address = map[i].address;
+			return map[i].name;
+		}
+	}
+	*address = FALSE;
+	return guid2string(guid);
+}
+
+/**
+ * Print a host from raw data and IP version
+ */
+static void print_host(FWP_IP_VERSION version, void *data)
+{
+	host_t *host = NULL;
+	UINT32 ints[4];
+
+	switch (version)
+	{
+		case FWP_IP_VERSION_V4:
+			ints[0] = untoh32(data);
+			host = host_create_from_chunk(AF_INET, chunk_from_thing(ints[0]), 0);
+			break;
+		case FWP_IP_VERSION_V6:
+			ints[3] = untoh32(data);
+			ints[2] = untoh32(data + 4);
+			ints[1] = untoh32(data + 8);
+			ints[0] = untoh32(data + 12);
+			host = host_create_from_chunk(AF_INET6, chunk_from_thing(ints), 0);
+			break;
+		default:
+			break;
+	}
+	if (host)
+	{
+		printf("%H", host);
+		host->destroy(host);
+	}
+}
+
+/**
+ * Print IPSEC_SA_AUTH_INFORMATION0
+ */
+static void print_auth(IPSEC_SA_AUTH_INFORMATION0 *a)
+{
+	printf("%N-%N",
+		auth_type_names, a->authTransform.authTransformId.authType,
+		auth_config_names, a->authTransform.authTransformId.authConfig);
+}
+
+/**
+ * Print IPSEC_SA_CIPHER_INFORMATION0
+ */
+static void print_cipher(IPSEC_SA_CIPHER_INFORMATION0 *c)
+{
+	printf("%N-%N",
+		cipher_type_names, c->cipherTransform.cipherTransformId.cipherType,
+		cipher_config_names, c->cipherTransform.cipherTransformId.cipherConfig);
+}
+
+/**
+ * Print IPsec SA transform
+ */
+static void list_sa(HANDLE engine, IPSEC_SA0 *sa)
+{
+	printf("    SPI 0x%08x\n", sa->spi);
+	switch (sa->saTransformType)
+	{
+		case IPSEC_TRANSFORM_AH:
+			printf("      AH: ");
+			print_auth(sa->ahInformation);
+			break;
+		case IPSEC_TRANSFORM_ESP_AUTH:
+			printf("      ESP: ");
+			print_auth(sa->espAuthInformation);
+			break;
+		case IPSEC_TRANSFORM_ESP_CIPHER:
+			printf("      ESP: ");
+			print_cipher(sa->espCipherInformation);
+			break;
+		case IPSEC_TRANSFORM_ESP_AUTH_AND_CIPHER:
+			printf("      ESP: ");
+			print_auth(&sa->espAuthAndCipherInformation->saAuthInformation);
+			printf(", ");
+			print_cipher(&sa->espAuthAndCipherInformation->saCipherInformation);
+			break;
+		default:
+			printf("      (Transform %d)", sa->saTransformType);
+			break;
+	}
+	printf("\n");
+}
+
+/**
+ * List a filter condition value, optionally as IP address
+ */
+static void print_value(FWP_CONDITION_VALUE0 *value, bool address)
+{
+	chunk_t chunk;
+
+	switch (value->type)
+	{
+		case FWP_EMPTY:
+			printf("empty");
+			break;
+		case FWP_UINT8:
+			printf("%u", value->uint8);
+			break;
+		case FWP_UINT16:
+			printf("%u", value->uint16);
+			break;
+		case FWP_UINT32:
+			if (address)
+			{
+				print_host(FWP_IP_VERSION_V4, &value->uint32);
+			}
+			else
+			{
+				printf("%u", value->uint32);
+			}
+			break;
+		case FWP_UINT64:
+			printf("%llu", value->uint64);
+			break;
+		case FWP_INT8:
+			printf("%d", value->int8);
+			break;
+		case FWP_INT16:
+			printf("%d", value->int16);
+			break;
+		case FWP_INT32:
+			printf("%d", value->int32);
+			break;
+		case FWP_INT64:
+			printf("%lld", value->int64);
+			break;
+		case FWP_FLOAT:
+			printf("%f", value->float32);
+			break;
+		case FWP_DOUBLE:
+			printf("%lf", value->double64);
+			break;
+		case FWP_BYTE_ARRAY16_TYPE:
+			if (address)
+			{
+				print_host(FWP_IP_VERSION_V6, value->byteArray16);
+			}
+			else
+			{
+				chunk = chunk_create((u_char*)value->byteArray16, 16);
+				printf("%#B", &chunk);
+			}
+			break;
+		case FWP_BYTE_BLOB_TYPE:
+			chunk = chunk_create(value->byteBlob->data, value->byteBlob->size);
+			printf("%#B", &chunk);
+			break;
+		case FWP_V4_ADDR_MASK:
+			print_host(FWP_IP_VERSION_V4, &value->v4AddrMask->addr);
+			printf("/");
+			print_host(FWP_IP_VERSION_V4, &value->v4AddrMask->mask);
+			break;
+		case FWP_V6_ADDR_MASK:
+			print_host(FWP_IP_VERSION_V6, &value->v6AddrMask->addr);
+			printf("/%u", &value->v6AddrMask->prefixLength);
+			break;
+		case FWP_RANGE_TYPE:
+			print_value((FWP_CONDITION_VALUE0*)&value->rangeValue->valueLow,
+						address);
+			printf(" - ");
+			print_value((FWP_CONDITION_VALUE0*)&value->rangeValue->valueHigh,
+						address);
+			break;
+		default:
+			printf("(unsupported)");
+			break;
+	}
+}
+
+/**
+ * List a filter condition
+ */
+static void list_cond(HANDLE engine, FWPM_FILTER_CONDITION0 *cond)
+{
+	bool address;
+
+	printf("      '%s' %N '", cond2name(&cond->fieldKey, &address),
+		match_type_names, cond->matchType);
+	print_value(&cond->conditionValue, address);
+	printf("'\n");
+}
+
+/**
+ * Print IPsec SA details
+ */
+static void list_details(HANDLE engine, IPSEC_SA_DETAILS1 *details)
+{
+	int i;
+
+	printf("  %sbound SA: ",
+		details->saDirection == FWP_DIRECTION_INBOUND ? "In" : "Out");
+	print_host(details->traffic.ipVersion, &details->traffic.localV4Address);
+	printf(" %s ", details->saDirection == FWP_DIRECTION_INBOUND ? "<-" : "->");
+	print_host(details->traffic.ipVersion, &details->traffic.remoteV4Address);
+	printf("\n    %N, flags: 0x%06x, lifetime: %us\n",
+		  traffic_type_names, details->traffic.trafficType,
+		  details->saBundle.flags, details->saBundle.lifetime.lifetimeSeconds);
+	if (details->udpEncapsulation)
+	{
+		printf("    UDP encap ports %u - %u\n",
+			details->udpEncapsulation->localUdpEncapPort,
+			details->udpEncapsulation->remoteUdpEncapPort);
+	}
+	for (i = 0; i < details->saBundle.numSAs; i++)
+	{
+		list_sa(engine, &details->saBundle.saList[i]);
+	}
+	printf("    Filter ID %llu\n", details->transportFilter->filterId);
+	for (i = 0; i < details->transportFilter->numFilterConditions; i++)
+	{
+		list_cond(engine, &details->transportFilter->filterCondition[i]);
+	}
+}
+
+/**
+ * List installed SA contexts
+ */
+static bool list_contexts(HANDLE engine)
+{
+	HANDLE handle;
+	UINT32 returned;
+	DWORD res;
+	IPSEC_SA_CONTEXT1 **entries;
+
+	res = IPsecSaContextCreateEnumHandle0(engine, NULL, &handle);
+	if (res != ERROR_SUCCESS)
+	{
+		fprintf(stderr, "IPsecSaContextCreateEnumHandle0(): 0x%08x\n", res);
+		return FALSE;
+	}
+
+	while (TRUE)
+	{
+		res = IPsecSaContextEnum1(engine, handle, 1, &entries, &returned);
+		if (res != ERROR_SUCCESS)
+		{
+			fprintf(stderr, "IPsecSaContextEnum1(): 0x%08x\n", res);
+			IPsecSaContextDestroyEnumHandle0(engine, handle);
+			return FALSE;
+		}
+		if (returned == 0)
+		{
+			break;
+		}
+
+		printf("SA context %llu:\n", entries[0]->saContextId);
+		list_details(engine, entries[0]->inboundSa);
+		list_details(engine, entries[0]->outboundSa);
+
+		FwpmFreeMemory0((void**)&entries);
+	}
+	IPsecSaContextDestroyEnumHandle0(engine, handle);
+	return TRUE;
+}
+
+const GUID FWPM_LAYER_IPSEC_KM_DEMUX_V4 = {
+	0xf02b1526, 0xa459, 0x4a51, { 0xb9, 0xe3, 0x75, 0x9d, 0xe5, 0x2b, 0x9d, 0x2c }
+};
+const GUID FWPM_LAYER_IPSEC_KM_DEMUX_V6 = {
+	0x2f755cf6, 0x2fd4, 0x4e88, { 0xb3, 0xe4, 0xa9, 0x1b, 0xca, 0x49, 0x52, 0x35 }
+};
+const GUID FWPM_LAYER_IPSEC_V4 = {
+	0xeda65c74, 0x610d, 0x4bc5, { 0x94, 0x8f, 0x3c, 0x4f, 0x89, 0x55, 0x68, 0x67 }
+};
+const GUID FWPM_LAYER_IPSEC_V6 = {
+	0x13c48442, 0x8d87, 0x4261, { 0x9a, 0x29, 0x59, 0xd2, 0xab, 0xc3, 0x48, 0xb4 }
+};
+const GUID FWPM_LAYER_IKEEXT_V4 = {
+	0xb14b7bdb, 0xdbbd, 0x473e, { 0xbe, 0xd4, 0x8b, 0x47, 0x08, 0xd4, 0xf2, 0x70 }
+};
+const GUID FWPM_LAYER_IKEEXT_V6 = {
+	0xb64786b3, 0xf687, 0x4eb9, { 0x89, 0xd2, 0x8e, 0xf3, 0x2a, 0xcd, 0xab, 0xe2 }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V4 = {
+	0xc86fd1bf, 0x21cd, 0x497e, { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD = {
+	0xb5a230d0, 0xa8c0, 0x44f2, { 0x91, 0x6e, 0x99, 0x1b, 0x53, 0xde, 0xd1, 0xf7 }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V6 = {
+	0xf52032cb, 0x991c, 0x46e7, { 0x97, 0x1d, 0x26, 0x01, 0x45, 0x9a, 0x91, 0xca }
+};
+const GUID FWPM_LAYER_INBOUND_IPPACKET_V6_DISCARD = {
+	0xbb24c279, 0x93b4, 0x47a2, { 0x83, 0xad, 0xae, 0x16, 0x98, 0xb5, 0x08, 0x85 }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V4 = {
+	0x1e5c9fae, 0x8a84, 0x4135, { 0xa3, 0x31, 0x95, 0x0b, 0x54, 0x22, 0x9e, 0xcd }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD = {
+	0x08e4bcb5, 0xb647, 0x48f3, { 0x95, 0x3c, 0xe5, 0xdd, 0xbd, 0x03, 0x93, 0x7e }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V6 = {
+	0xa3b3ab6b, 0x3564, 0x488c, { 0x91, 0x17, 0xf3, 0x4e, 0x82, 0x14, 0x27, 0x63 }
+};
+const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V6_DISCARD = {
+	0x9513d7c4, 0xa934, 0x49dc, { 0x91, 0xa7, 0x6c, 0xcb, 0x80, 0xcc, 0x02, 0xe3 }
+};
+const GUID FWPM_LAYER_IPFORWARD_V4_DISCARD = {
+	0x9e9ea773, 0x2fae, 0x4210, { 0x8f, 0x17, 0x34, 0x12, 0x9e, 0xf3, 0x69, 0xeb }
+};
+const GUID FWPM_LAYER_IPFORWARD_V6_DISCARD = {
+	0x31524a5d, 0x1dfe, 0x472f, { 0xbb, 0x93, 0x51, 0x8e, 0xe9, 0x45, 0xd8, 0xa2 }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD = {
+	0xac4a9833, 0xf69d, 0x4648, { 0xb2, 0x61, 0x6d, 0xc8, 0x48, 0x35, 0xef, 0x39 }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD = {
+	0x2a6ff955, 0x3b2b, 0x49d2, { 0x98, 0x48, 0xad, 0x9d, 0x72, 0xdc, 0xaa, 0xb7 }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD = {
+	0xc5f10551, 0xbdb0, 0x43d7, { 0xa3, 0x13, 0x50, 0xe2, 0x11, 0xf4, 0xd6, 0x8a }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD = {
+	0xf433df69, 0xccbd, 0x482e, { 0xb9, 0xb2, 0x57, 0x16, 0x56, 0x58, 0xc3, 0xb3 }
+};
+
+/**
+ * Convert filter layer GUID to name
+ */
+static char* layer2name(GUID *guid)
+{
+	struct {
+		GUID guid;
+		char *name;
+	} map[] = {
+		{ FWPM_LAYER_IPSEC_KM_DEMUX_V4, "IPsec KM demux v4" },
+		{ FWPM_LAYER_IPSEC_KM_DEMUX_V6, "IPsec KM demux v6" },
+		{ FWPM_LAYER_IPSEC_V4, "IPsec v4" },
+		{ FWPM_LAYER_IPSEC_V6, "IPsec v6" },
+		{ FWPM_LAYER_IKEEXT_V4, "IKE ext v4" },
+		{ FWPM_LAYER_IKEEXT_V6, "IKE ext v6" },
+		{ FWPM_LAYER_INBOUND_IPPACKET_V4, "inbound v4" },
+		{ FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD, "inbound v4 dsc" },
+		{ FWPM_LAYER_INBOUND_IPPACKET_V6, "inbound v6" },
+		{ FWPM_LAYER_INBOUND_IPPACKET_V6_DISCARD, "inbound v6 dsc" },
+		{ FWPM_LAYER_OUTBOUND_IPPACKET_V4, "outbound v4" },
+		{ FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD, "outbound v4 dsc" },
+		{ FWPM_LAYER_OUTBOUND_IPPACKET_V6, "outbound v6" },
+		{ FWPM_LAYER_OUTBOUND_IPPACKET_V6_DISCARD, "outbound v6 dsc" },
+		{ FWPM_LAYER_IPFORWARD_V4, "forward v4" },
+		{ FWPM_LAYER_IPFORWARD_V4_DISCARD, "forward v4 dsc" },
+		{ FWPM_LAYER_IPFORWARD_V6, "forward v6" },
+		{ FWPM_LAYER_IPFORWARD_V6_DISCARD, "forward v6 discard" },
+		{ FWPM_LAYER_INBOUND_TRANSPORT_V4, "inbound transport v4" },
+		{ FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD, "inbound transport v4 dsc" },
+		{ FWPM_LAYER_INBOUND_TRANSPORT_V6, "inbound transport v6" },
+		{ FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD, "inbound v6 transport dsc" },
+		{ FWPM_LAYER_OUTBOUND_TRANSPORT_V4, "outbound transport v4" },
+		{ FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD, "outbound transport v4 dsc" },
+		{ FWPM_LAYER_OUTBOUND_TRANSPORT_V6, "outbound transport v6" },
+		{ FWPM_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD, "outbound transport v6 dsc" },
+	};
+	int i;
+
+	for (i = 0; i < countof(map); i++)
+	{
+		if (memeq(&map[i].guid, guid, sizeof(GUID)))
+		{
+			return map[i].name;
+		}
+	}
+	return NULL;
+}
+
+/**
+ * Convert filter callout GUID to name
+ */
+static char* callout2name(GUID *guid)
+{
+	struct {
+		GUID guid;
+		char *name;
+	} map[] = {
+		{ FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4, "inbound transport v4" },
+		{ FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6, "inbound transport v6" },
+		{ FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4, "outbound transport v4" },
+		{ FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6, "outbound transport v6" },
+		{ FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4, "inbound tunnel v4" },
+		{ FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6, "inbound tunnel v6" },
+		{ FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4, "outbound tunnel v4" },
+		{ FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6, "outbound tunnel v6" },
+		{ FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4, "forward in tunnel v4" },
+		{ FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6, "forward in tunnel v6" },
+		{ FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4, "forward out tunnel v4" },
+		{ FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6, "forward out tunnel v6" },
+	};
+	int i;
+
+	for (i = 0; i < countof(map); i++)
+	{
+		if (memeq(&map[i].guid, guid, sizeof(GUID)))
+		{
+			return map[i].name;
+		}
+	}
+	return guid2string(guid);
+}
+
+/**
+ * Print display data with description
+ */
+static void print_display_data(FWPM_DISPLAY_DATA0 *data)
+{
+	char buf[128];
+
+	buf[0] = '\0';
+	if (data->name)
+	{
+		wcstombs(buf, data->name, sizeof(buf));
+	}
+	printf("%s", buf);
+	if (data->description)
+	{
+		buf[0] = '\0';
+		wcstombs(buf, data->description, sizeof(buf));
+		if (strlen(buf))
+		{
+			printf(" (%s)", buf);
+		}
+	}
+}
+
+/**
+ * List installed firewall filters
+ */
+static bool list_filters(HANDLE engine)
+{
+	HANDLE handle;
+	UINT32 returned;
+	DWORD res;
+	FWPM_FILTER0 **entries;
+	char *layer;
+	int i;
+
+	res = FwpmFilterCreateEnumHandle0(engine, NULL, &handle);
+	if (res != ERROR_SUCCESS)
+	{
+		fprintf(stderr, "FwpmFilterCreateEnumHandle0(): 0x%08x\n", res);
+		return FALSE;
+	}
+
+	while (TRUE)
+	{
+		res = FwpmFilterEnum0(engine, handle, 1, &entries, &returned);
+		if (res != ERROR_SUCCESS)
+		{
+			fprintf(stderr, "FwpmFilterEnum0(): 0x%08x\n", res);
+			FwpmFilterDestroyEnumHandle0(engine, handle);
+			return FALSE;
+		}
+		if (returned == 0)
+		{
+			break;
+		}
+
+		layer = layer2name(&entries[0]->layerKey);
+		if (layer)
+		{
+			printf("Filter ID %llu, '", entries[0]->filterId);
+			print_display_data(&entries[0]->displayData);
+			printf("'\n");
+			printf("  %s, ", layer);
+			if (entries[0]->effectiveWeight.type == FWP_UINT64)
+			{
+				printf("weight %016llx, ", *entries[0]->effectiveWeight.uint64);
+			}
+
+			switch (entries[0]->action.type)
+			{
+				case FWP_ACTION_BLOCK:
+					printf("block\n");
+					break;
+				case FWP_ACTION_PERMIT:
+					printf("permit\n");
+					break;
+				case FWP_ACTION_CALLOUT_TERMINATING:
+					printf("callout terminating: %s\n",
+						callout2name(&entries[0]->action.calloutKey));
+					break;
+				case FWP_ACTION_CALLOUT_INSPECTION:
+					printf("callout inspection: %s\n",
+						callout2name(&entries[0]->action.calloutKey));
+					break;
+				case FWP_ACTION_CALLOUT_UNKNOWN:
+					printf("callout unknown: %s\n",
+						callout2name(&entries[0]->action.calloutKey));
+					break;
+				default:
+					printf("(unknown action)\n");
+					break;
+			}
+			for (i = 0; i < entries[0]->numFilterConditions; i++)
+			{
+				list_cond(engine, &entries[0]->filterCondition[i]);
+			}
+		}
+		FwpmFreeMemory0((void**)&entries);
+	}
+	FwpmFilterDestroyEnumHandle0(engine, handle);
+	return TRUE;
+}
+
+/**
+ * ipsecdump main()
+ */
+int main(int argc, char *argv[])
+{
+	FWPM_SESSION0 session = {
+		.displayData = {
+			.name = L"ipsecdump",
+			.description = L"strongSwan SAD/SPD dumper",
+		},
+	};
+	HANDLE engine;
+	DWORD res;
+	int code;
+
+	library_init(NULL, "ipsecdump");
+	atexit(library_deinit);
+
+	res = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine);
+	if (res != ERROR_SUCCESS)
+	{
+		fprintf(stderr, "FwpmEngineOpen(): 0x%08x\n", res);
+		return 2;
+	}
+	if (argc > 1 && streq(argv[1], "filters"))
+	{
+		code = list_filters(engine) ? 0 : 1;
+	}
+	else
+	{
+		code = list_contexts(engine) ? 0 : 1;
+	}
+	FwpmEngineClose0(engine);
+	return code;
+}
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c
new file mode 100644
index 0000000..41f85ba
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+
+const GUID FWPM_CONDITION_IP_REMOTE_ADDRESS = {
+	0xb235ae9a, 0x1d64, 0x49b8, { 0xa4,0x4c,0x5f,0xf3,0xd9,0x09,0x50,0x45 }
+};
+const GUID FWPM_CONDITION_IP_LOCAL_ADDRESS = {
+	0xd9ee00de, 0xc1ef, 0x4617, { 0xbf,0xe3,0xff,0xd8,0xf5,0xa0,0x89,0x57 }
+};
+const GUID FWPM_CONDITION_IP_SOURCE_ADDRESS = {
+	0xae96897e, 0x2e94, 0x4bc9, { 0xb3,0x13,0xb2,0x7e,0xe8,0x0e,0x57,0x4d }
+};
+const GUID FWPM_CONDITION_IP_DESTINATION_ADDRESS = {
+	0x2d79133b, 0xb390, 0x45c6, { 0x86,0x99,0xac,0xac,0xea,0xaf,0xed,0x33 }
+};
+const GUID FWPM_CONDITION_IP_LOCAL_PORT = {
+	0x0c1ba1af, 0x5765, 0x453f, { 0xaf,0x22,0xa8,0xf7,0x91,0xac,0x77,0x5b }
+};
+const GUID FWPM_CONDITION_IP_REMOTE_PORT = {
+	0xc35a604d, 0xd22b, 0x4e1a, { 0x91,0xb4,0x68,0xf6,0x74,0xee,0x67,0x4b }
+};
+const GUID FWPM_CONDITION_IP_PROTOCOL = {
+	0x3971ef2b, 0x623e, 0x4f9a, { 0x8c,0xb1,0x6e,0x79,0xb8,0x06,0xb9,0xa7 }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V4 = {
+	0x5926dfc8, 0xe3cf, 0x4426, { 0xa2,0x83,0xdc,0x39,0x3f,0x5d,0x0f,0x9d }
+};
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V6 = {
+	0x634a869f, 0xfc23, 0x4b90, { 0xb0,0xc1,0xbf,0x62,0x0a,0x36,0xae,0x6f }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4 = {
+	0x09e61aea, 0xd214, 0x46e2, { 0x9b,0x21,0xb2,0x6b,0x0b,0x2f,0x28,0xc8 }
+};
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6 = {
+	0xe1735bde, 0x013f, 0x4655, { 0xb3,0x51,0xa4,0x9e,0x15,0x76,0x2d,0xf0 }
+};
+const GUID FWPM_LAYER_IPFORWARD_V4 = {
+	0xa82acc24, 0x4ee1, 0x4ee1, { 0xb4,0x65,0xfd,0x1d,0x25,0xcb,0x10,0xa4}
+};
+const GUID FWPM_LAYER_IPFORWARD_V6 = {
+	0x7b964818, 0x19c7, 0x493a, { 0xb7,0x1f,0x83,0x2c,0x36,0x84,0xd2,0x8c }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4 = {
+	0x5132900d, 0x5e84, 0x4b5f, { 0x80,0xe4,0x01,0x74,0x1e,0x81,0xff,0x10 }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6 = {
+	0x49d3ac92, 0x2a6c, 0x4dcf, { 0x95,0x5f,0x1c,0x3b,0xe0,0x09,0xdd,0x99 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4 = {
+	0x4b46bf0a, 0x4523, 0x4e57, { 0xaa,0x38,0xa8,0x79,0x87,0xc9,0x10,0xd9 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6 = {
+	0x38d87722, 0xad83, 0x4f11, { 0xa9,0x1f,0xdf,0x0f,0xb0,0x77,0x22,0x5b }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4 = {
+	0x191a8a46, 0x0bf8, 0x46cf, { 0xb0,0x45,0x4b,0x45,0xdf,0xa6,0xa3,0x24 }
+};
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6 = {
+	0x80c342e3, 0x1e53, 0x4d6f, { 0x9b,0x44,0x03,0xdf,0x5a,0xee,0xe1,0x54 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4 = {
+	0x70a4196c, 0x835b, 0x4fb0, { 0x98,0xe8,0x07,0x5f,0x4d,0x97,0x7d,0x46 }
+};
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6 = {
+	0xf1835363, 0xa6a5, 0x4e62, { 0xb1,0x80,0x23,0xdb,0x78,0x9d,0x8d,0xa6 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4 = {
+	0x28829633, 0xc4f0, 0x4e66, { 0x87,0x3f,0x84,0x4d,0xb2,0xa8,0x99,0xc7 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6 = {
+	0xaf50bec2, 0xc686, 0x429a, { 0x88,0x4d,0xb7,0x44,0x43,0xe7,0xb0,0xb4 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4 = {
+	0xfb532136, 0x15cb, 0x440b, { 0x93,0x7c,0x17,0x17,0xca,0x32,0x0c,0x40 }
+};
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6 = {
+	0xdae640cc, 0xe021, 0x4bee, { 0x9e,0xb6,0xa4,0x8b,0x27,0x5c,0x8c,0x1d }
+};
+
+/**
+ * Load a function symbol from a loaded dll
+ */
+static inline void *load_function(char *dll, char *name)
+{
+	HANDLE handle;
+	void *sym = NULL;
+
+	handle = GetModuleHandle(dll);
+	if (!handle)
+	{
+		return NULL;
+	}
+	sym = GetProcAddress(handle, name);
+	return sym;
+}
+
+/**
+ * Macro that defines a stub for a function that calls the same DLL function
+ *
+ * @param dll		DLL to find function in
+ * @param ret		return type of function
+ * @param name		function name
+ * @param size		size of all arguments on stack
+ * @param ...		arguments of function
+ */
+#define STUB(dll, ret, name, size, ...) \
+ret WINAPI name(__VA_ARGS__) \
+{ \
+	static void (*fun)() = NULL; \
+	if (!fun) \
+	{ \
+		fun = load_function(#dll, #name); \
+	} \
+	if (fun) \
+	{ \
+		__builtin_return(__builtin_apply(fun, __builtin_apply_args(), size)); \
+	} \
+	return ERROR_NOT_SUPPORTED; \
+}
+
+STUB(fwpuclnt, DWORD, IPsecSaContextCreate1, 40,
+	HANDLE engineHandle, const void *outboundTraffic,
+	const void *virtualIfTunnelInfo, UINT64 *inboundFilterId, UINT64 *id)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextSetSpi0, 32,
+	HANDLE engineHandle, UINT64 id, const void *getSpi, UINT32 inboundSpi)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextGetById1, 24,
+	HANDLE engineHandle, UINT64 id, void **saContext)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextUpdate0, 24,
+	HANDLE engineHandle, UINT32 flags, const void *newValues)
+
+STUB(fwpuclnt, DWORD, IPsecSaContextEnum1, 40,
+	HANDLE engineHandle, HANDLE enumHandle, UINT32 numEntriesRequested,
+	void ***entries, UINT32 *numEntriesReturned)
+
+STUB(fwpuclnt, DWORD, FwpmNetEventSubscribe0, 40,
+	HANDLE engineHandle, const void *subscription, void(*callback)(),
+	void *context, HANDLE *eventsHandle)
+
+STUB(fwpuclnt, DWORD, FwpmNetEventUnsubscribe0, 16,
+	HANDLE engineHandle, HANDLE eventsHandle)
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h
new file mode 100644
index 0000000..50a89a0
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_compat.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup kernel_wfp_compat kernel_wfp_compat
+ * @{ @ingroup kernel_wfp
+ */
+
+#ifndef KERNEL_WFP_COMPAT_H_
+#define KERNEL_WFP_COMPAT_H_
+
+#include <winsock2.h>
+#include <windows.h>
+#include <ipsectypes.h>
+
+/* MinGW defines CIPHERs incorrectly starting at 0 */
+#define IPSEC_CIPHER_TYPE_DES					1
+#define IPSEC_CIPHER_TYPE_3DES					2
+#define IPSEC_CIPHER_TYPE_AES_128				3
+#define IPSEC_CIPHER_TYPE_AES_192				4
+#define IPSEC_CIPHER_TYPE_AES_256				5
+#define IPSEC_CIPHER_TYPE_MAX					6
+
+#include <fwpmtypes.h>
+#include <fwpmu.h>
+#undef interface
+
+/* MinGW defines TRANSFORMs incorrectly starting at 0 */
+#define IPSEC_TRANSFORM_AH						1
+#define IPSEC_TRANSFORM_ESP_AUTH				2
+#define IPSEC_TRANSFORM_ESP_CIPHER				3
+#define IPSEC_TRANSFORM_ESP_AUTH_AND_CIPHER		4
+#define IPSEC_TRANSFORM_ESP_AUTH_FW				5
+#define IPSEC_TRANSFORM_TYPE_MAX				6
+
+/* missing in MinGW */
+enum {
+	FWPM_TUNNEL_FLAG_POINT_TO_POINT = 						(1<<0),
+	FWPM_TUNNEL_FLAG_ENABLE_VIRTUAL_IF_TUNNELING =			(1<<1),
+};
+
+/* missing in MinGW */
+enum {
+	IPSEC_SA_DETAILS_UPDATE_TRAFFIC =						(1<<0),
+	IPSEC_SA_DETAILS_UPDATE_UDP_ENCAPSULATION =				(1<<1),
+	IPSEC_SA_BUNDLE_UPDATE_FLAGS =							(1<<2),
+	IPSEC_SA_BUNDLE_UPDATE_NAP_CONTEXT =					(1<<3),
+	IPSEC_SA_BUNDLE_UPDATE_KEY_MODULE_STATE =				(1<<4),
+	IPSEC_SA_BUNDLE_UPDATE_PEER_V4_PRIVATE_ADDRESS =		(1<<5),
+	IPSEC_SA_BUNDLE_UPDATE_MM_SA_ID =						(1<<6),
+};
+
+/* missing in MinGW */
+enum {
+	FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET =					(1<<0),
+	FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET =					(1<<1),
+	FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET =					(1<<2),
+	FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET =					(1<<3),
+	FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET =					(1<<4),
+	FWPM_NET_EVENT_FLAG_APP_ID_SET =						(1<<5),
+	FWPM_NET_EVENT_FLAG_USER_ID_SET =						(1<<6),
+	FWPM_NET_EVENT_FLAG_SCOPE_ID_SET =						(1<<7),
+	FWPM_NET_EVENT_FLAG_IP_VERSION_SET =					(1<<8),
+	FWPM_NET_EVENT_FLAG_REAUTH_REASON_SET =					(1<<9),
+};
+
+/* missing in MinGW */
+enum {
+	FWPM_FILTER_FLAG_PERSISTENT =							(1<<0),
+	FWPM_FILTER_FLAG_BOOTTIME =								(1<<1),
+	FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT =					(1<<2),
+	FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT =					(1<<3),
+	FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED =		(1<<4),
+	FWPM_FILTER_FLAG_DISABLED =								(1<<5),
+};
+
+/* missing in MinGW */
+enum {
+	IPSEC_SA_BUNDLE_FLAG_ND_SECURE =							(1<< 0),
+	IPSEC_SA_BUNDLE_FLAG_ND_BOUNDARY =							(1<< 1),
+	IPSEC_SA_BUNDLE_FLAG_ND_PEER_NAT_BOUNDARY =					(1<< 2),
+	IPSEC_SA_BUNDLE_FLAG_GUARANTEE_ENCRYPTION =					(1<< 3),
+	IPSEC_SA_BUNDLE_FLAG_NLB =									(1<< 4),
+	IPSEC_SA_BUNDLE_FLAG_NO_MACHINE_LUID_VERIFY =				(1<< 5),
+	IPSEC_SA_BUNDLE_FLAG_NO_IMPERSONATION_LUID_VERIFY =			(1<< 6),
+	IPSEC_SA_BUNDLE_FLAG_NO_EXPLICIT_CRED_MATCH =				(1<< 7),
+	IPSEC_SA_BUNDLE_FLAG_ALLOW_NULL_TARGET_NAME_MATCH =			(1<< 9),
+	IPSEC_SA_BUNDLE_FLAG_CLEAR_DF_ON_TUNNEL =					(1<<10),
+	IPSEC_SA_BUNDLE_FLAG_ASSUME_UDP_CONTEXT_OUTBOUND =			(1<<11),
+	IPSEC_SA_BUNDLE_FLAG_ND_PEER_BOUNDARY =						(1<<12),
+	IPSEC_SA_BUNDLE_FLAG_SUPPRESS_DUPLICATE_DELETION =			(1<<13),
+	IPSEC_SA_BUNDLE_FLAG_PEER_SUPPORTS_GUARANTEE_ENCRYPTION =	(1<<14),
+	IPSEC_SA_BUNDLE_FLAG_FORCE_INBOUND_CONNECTIONS =			(1<<15),
+	IPSEC_SA_BUNDLE_FLAG_FORCE_OUTBOUND_CONNECTIONS =			(1<<16),
+	IPSEC_SA_BUNDLE_FLAG_FORWARD_PATH_INITIATOR =				(1<<17),
+};
+
+/* missing in some MinGW versions */
+const GUID FWPM_CONDITION_IP_REMOTE_ADDRESS;
+const GUID FWPM_CONDITION_IP_LOCAL_ADDRESS;
+const GUID FWPM_CONDITION_IP_SOURCE_ADDRESS;
+const GUID FWPM_CONDITION_IP_DESTINATION_ADDRESS;
+const GUID FWPM_CONDITION_IP_LOCAL_PORT;
+const GUID FWPM_CONDITION_IP_REMOTE_PORT;
+const GUID FWPM_CONDITION_IP_PROTOCOL;
+#ifndef FWPM_CONDITION_ICMP_TYPE
+# define FWPM_CONDITION_ICMP_TYPE FWPM_CONDITION_IP_LOCAL_PORT
+#endif
+#ifndef FWPM_CONDITION_ICMP_CODE
+# define FWPM_CONDITION_ICMP_CODE FWPM_CONDITION_IP_REMOTE_PORT
+#endif
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V4;
+const GUID FWPM_LAYER_INBOUND_TRANSPORT_V6;
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
+const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6;
+const GUID FWPM_LAYER_IPFORWARD_V4;
+const GUID FWPM_LAYER_IPFORWARD_V6;
+const GUID FWPM_SUBLAYER_IPSEC_TUNNEL;
+const GUID FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4;
+const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6;
+
+/* integrity config, missing in some MinGW versions */
+#ifndef IPSEC_AUTH_CONFIG_HMAC_MD5_96
+enum {
+	IPSEC_AUTH_CONFIG_HMAC_MD5_96 = 0,
+	IPSEC_AUTH_CONFIG_HMAC_SHA_1_96,
+	IPSEC_AUTH_CONFIG_HMAC_SHA_256_128,
+	IPSEC_AUTH_CONFIG_GCM_AES_128,
+	IPSEC_AUTH_CONFIG_GCM_AES_192,
+	IPSEC_AUTH_CONFIG_GCM_AES_256,
+	IPSEC_AUTH_CONFIG_MAX
+};
+#define IPSEC_AUTH_TRANSFORM_ID_HMAC_MD5_96 { \
+  IPSEC_AUTH_MD5, IPSEC_AUTH_CONFIG_HMAC_MD5_96 }
+#define IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96 { \
+  IPSEC_AUTH_SHA_1, IPSEC_AUTH_CONFIG_HMAC_SHA_1_96 }
+#define IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_256_128 { \
+  IPSEC_AUTH_SHA_256, IPSEC_AUTH_CONFIG_HMAC_SHA_256_128 }
+#define IPSEC_AUTH_TRANSFORM_ID_GCM_AES_128 { \
+  IPSEC_AUTH_AES_128, IPSEC_AUTH_CONFIG_GCM_AES_128 }
+#define IPSEC_AUTH_TRANSFORM_ID_GCM_AES_192 { \
+  IPSEC_AUTH_AES_192, IPSEC_AUTH_CONFIG_GCM_AES_192 }
+#define IPSEC_AUTH_TRANSFORM_ID_GCM_AES_256 { \
+  IPSEC_AUTH_AES_256, IPSEC_AUTH_CONFIG_GCM_AES_256 }
+#endif
+
+/* encryption config, missing in some MinGW versions */
+#ifndef IPSEC_CIPHER_CONFIG_CBC_DES
+enum {
+	IPSEC_CIPHER_CONFIG_CBC_DES = 1,
+	IPSEC_CIPHER_CONFIG_CBC_3DES,
+	IPSEC_CIPHER_CONFIG_CBC_AES_128,
+	IPSEC_CIPHER_CONFIG_CBC_AES_192,
+	IPSEC_CIPHER_CONFIG_CBC_AES_256,
+	IPSEC_CIPHER_CONFIG_GCM_AES_128,
+	IPSEC_CIPHER_CONFIG_GCM_AES_192,
+	IPSEC_CIPHER_CONFIG_GCM_AES_256,
+	IPSEC_CIPHER_CONFIG_MAX
+};
+#define IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_128 { \
+  IPSEC_CIPHER_TYPE_AES_128, IPSEC_CIPHER_CONFIG_GCM_AES_128 }
+#define IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_192 { \
+  IPSEC_CIPHER_TYPE_AES_192, IPSEC_CIPHER_CONFIG_GCM_AES_192 }
+#define IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_256 { \
+  IPSEC_CIPHER_TYPE_AES_256, IPSEC_CIPHER_CONFIG_GCM_AES_256 }
+#define IPSEC_CIPHER_TRANSFORM_ID_CBC_DES { \
+  IPSEC_CIPHER_TYPE_DES, IPSEC_CIPHER_CONFIG_CBC_DES }
+#define IPSEC_CIPHER_TRANSFORM_ID_CBC_3DES { \
+  IPSEC_CIPHER_TYPE_3DES, IPSEC_CIPHER_CONFIG_CBC_3DES }
+#define IPSEC_CIPHER_TRANSFORM_ID_AES_128 { \
+  IPSEC_CIPHER_TYPE_AES_128, IPSEC_CIPHER_CONFIG_CBC_AES_128 }
+#define IPSEC_CIPHER_TRANSFORM_ID_AES_192 { \
+  IPSEC_CIPHER_TYPE_AES_192, IPSEC_CIPHER_CONFIG_CBC_AES_192 }
+#define IPSEC_CIPHER_TRANSFORM_ID_AES_256 { \
+  IPSEC_CIPHER_TYPE_AES_256, IPSEC_CIPHER_CONFIG_CBC_AES_256 }
+#endif
+
+DWORD WINAPI FwpmIPsecTunnelAdd0(HANDLE, UINT32,
+	const FWPM_PROVIDER_CONTEXT0*, const FWPM_PROVIDER_CONTEXT0*, UINT32,
+	const FWPM_FILTER_CONDITION0*, PSECURITY_DESCRIPTOR);
+
+#endif /** KERNEL_WFP_COMPAT_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
new file mode 100644
index 0000000..c788bfb
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.c
@@ -0,0 +1,2551 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/* Windows 7, for some fwpmu.h functionality */
+#define _WIN32_WINNT 0x0601
+
+#include "kernel_wfp_compat.h"
+#include "kernel_wfp_ipsec.h"
+
+#include <daemon.h>
+#include <hydra.h>
+#include <threading/mutex.h>
+#include <collections/array.h>
+#include <collections/hashtable.h>
+#include <processing/jobs/callback_job.h>
+
+
+typedef struct private_kernel_wfp_ipsec_t private_kernel_wfp_ipsec_t;
+
+struct private_kernel_wfp_ipsec_t {
+
+	/**
+	 * Public interface
+	 */
+	kernel_wfp_ipsec_t public;
+
+	/**
+	 * Next SPI to allocate
+	 */
+	refcount_t nextspi;
+
+	/**
+	 * Mix value to distribute SPI allocation randomly
+	 */
+	u_int32_t mixspi;
+
+	/**
+	 * IKE bypass filters, as UINT64 filter LUID
+	 */
+	array_t *bypass;
+
+	/**
+	 * Temporary SAD/SPD entries referenced reqid, as uintptr_t => entry_t
+	 */
+	hashtable_t *tsas;
+
+	/**
+	 * SAD/SPD entries referenced by inbound SA, as sa_entry_t => entry_t
+	 */
+	hashtable_t *isas;
+
+	/**
+	 * SAD/SPD entries referenced by outbound SA, as sa_entry_t => entry_t
+	 */
+	hashtable_t *osas;
+
+	/**
+	 * Installed routes, as route_t => route_t
+	 */
+	hashtable_t *routes;
+
+	/**
+	 * Installed traps, as trap_t => trap_t
+	 */
+	hashtable_t *traps;
+
+	/**
+	 * Mutex for accessing entries
+	 */
+	mutex_t *mutex;
+
+	/**
+	 * WFP session handle
+	 */
+	HANDLE handle;
+
+	/**
+	 * Provider charon registers as
+	 */
+	FWPM_PROVIDER0 provider;
+
+	/**
+	 * Event handle
+	 */
+	HANDLE event;
+};
+
+/**
+ * Security association entry
+ */
+typedef struct {
+	/** SPI for this SA */
+	u_int32_t spi;
+	/** protocol, IPPROTO_ESP/IPPROTO_AH */
+	u_int8_t protocol;
+	/** hard lifetime of SA */
+	u_int32_t lifetime;
+	/** destination host address for this SPI */
+	host_t *dst;
+	struct {
+		/** algorithm */
+		u_int16_t alg;
+		/** key */
+		chunk_t key;
+	} integ, encr;
+} sa_entry_t;
+
+/**
+ * Hash function for sas lookup table
+ */
+static u_int hash_sa(sa_entry_t *key)
+{
+	return chunk_hash_inc(chunk_from_thing(key->spi),
+						  chunk_hash(key->dst->get_address(key->dst)));
+}
+
+/**
+ * equals function for sas lookup table
+ */
+static bool equals_sa(sa_entry_t *a, sa_entry_t *b)
+{
+	return a->spi == b->spi && a->dst->ip_equals(a->dst, b->dst);
+}
+
+/**
+ * Security policy entry
+ */
+typedef struct {
+	/** policy source addresses */
+	traffic_selector_t *src;
+	/** policy destinaiton addresses */
+	traffic_selector_t *dst;
+	/** WFP allocated LUID for inbound filter ID */
+	u_int64_t policy_in;
+	/** WFP allocated LUID for outbound filter ID */
+	u_int64_t policy_out;
+	/** WFP allocated LUID for forward inbound filter ID, tunnel mode only */
+	u_int64_t policy_fwd_in;
+	/** WFP allocated LUID for forward outbound filter ID, tunnel mode only */
+	u_int64_t policy_fwd_out;
+	/** have installed a route for it? */
+	bool route;
+} sp_entry_t;
+
+/**
+ * Destroy an SP entry
+ */
+static void sp_entry_destroy(sp_entry_t *sp)
+{
+	sp->src->destroy(sp->src);
+	sp->dst->destroy(sp->dst);
+	free(sp);
+}
+
+/**
+ * Collection of SA/SP database entries for a reqid
+ */
+typedef struct {
+	/** reqid of entry */
+	u_int32_t reqid;
+	/** outer address on local host */
+	host_t *local;
+	/** outer address on remote host */
+	host_t *remote;
+	/** inbound SA entry */
+	sa_entry_t isa;
+	/** outbound SA entry */
+	sa_entry_t osa;
+	/** associated (outbound) policies, as sp_entry_t* */
+	array_t *sps;
+	/** IPsec mode, tunnel|transport */
+	ipsec_mode_t mode;
+	/** UDP encapsulation */
+	bool encap;
+	/** provider context, for tunnel mode only */
+	u_int64_t provider;
+	/** WFP allocated LUID for SA context */
+	u_int64_t sa_id;
+} entry_t;
+
+/**
+ * Installed route
+ */
+typedef struct {
+	/** destination net of route */
+	host_t *dst;
+	/** prefix length of dst */
+	u_int8_t mask;
+	/** source address for route */
+	host_t *src;
+	/** gateway of route, NULL if directly attached */
+	host_t *gtw;
+	/** references for route */
+	u_int refs;
+} route_t;
+
+/**
+ * Destroy a route_t
+ */
+static void destroy_route(route_t *this)
+{
+	this->dst->destroy(this->dst);
+	this->src->destroy(this->src);
+	DESTROY_IF(this->gtw);
+	free(this);
+}
+
+/**
+ * Hashtable equals function for routes
+ */
+static bool equals_route(route_t *a, route_t *b)
+{
+	return a->mask == b->mask &&
+		   a->dst->ip_equals(a->dst, b->dst) &&
+		   a->src->ip_equals(a->src, b->src);
+}
+
+/**
+ * Hashtable hash function for routes
+ */
+static u_int hash_route(route_t *route)
+{
+	return chunk_hash_inc(route->src->get_address(route->src),
+			chunk_hash_inc(route->dst->get_address(route->dst), route->mask));
+}
+
+/** forward declaration */
+static bool manage_routes(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+						  bool add);
+
+/**
+ * Remove policies associated to an entry from kernel
+ */
+static void cleanup_policies(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+	enumerator_t *enumerator;
+	sp_entry_t *sp;
+
+	if (entry->mode == MODE_TUNNEL)
+	{
+		manage_routes(this, entry, FALSE);
+	}
+
+	enumerator = array_create_enumerator(entry->sps);
+	while (enumerator->enumerate(enumerator, &sp))
+	{
+		if (sp->policy_in)
+		{
+			FwpmFilterDeleteById0(this->handle, sp->policy_in);
+			sp->policy_in = 0;
+		}
+		if (sp->policy_out)
+		{
+			FwpmFilterDeleteById0(this->handle, sp->policy_out);
+			sp->policy_out = 0;
+		}
+		if (sp->policy_fwd_in)
+		{
+			FwpmFilterDeleteById0(this->handle, sp->policy_fwd_in);
+			sp->policy_fwd_in = 0;
+		}
+		if (sp->policy_fwd_out)
+		{
+			FwpmFilterDeleteById0(this->handle, sp->policy_fwd_out);
+			sp->policy_fwd_out = 0;
+		}
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Destroy a SA/SP entry set
+ */
+static void entry_destroy(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+	if (entry->sa_id)
+	{
+		IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+	}
+	if (entry->provider)
+	{
+		FwpmProviderContextDeleteById0(this->handle, entry->provider);
+	}
+	cleanup_policies(this, entry);
+	array_destroy_function(entry->sps, (void*)sp_entry_destroy, NULL);
+	entry->local->destroy(entry->local);
+	entry->remote->destroy(entry->remote);
+	chunk_clear(&entry->isa.integ.key);
+	chunk_clear(&entry->isa.encr.key);
+	chunk_clear(&entry->osa.integ.key);
+	chunk_clear(&entry->osa.encr.key);
+	free(entry);
+}
+
+/**
+ * Append/Realloc a filter condition to an existing condition set
+ */
+static FWPM_FILTER_CONDITION0 *append_condition(FWPM_FILTER_CONDITION0 *conds[],
+												int *count)
+{
+	FWPM_FILTER_CONDITION0 *cond;
+
+	(*count)++;
+	*conds = realloc(*conds, *count * sizeof(*cond));
+	cond = *conds + *count - 1;
+	memset(cond, 0, sizeof(*cond));
+
+	return cond;
+}
+
+/**
+ * Convert an IPv4 prefix to a host order subnet mask
+ */
+static u_int32_t prefix2mask(u_int8_t prefix)
+{
+	u_int8_t netmask[4] = {};
+	int i;
+
+	for (i = 0; i < sizeof(netmask); i++)
+	{
+		if (prefix < 8)
+		{
+			netmask[i] = 0xFF << (8 - prefix);
+			break;
+		}
+		netmask[i] = 0xFF;
+		prefix -= 8;
+	}
+	return untoh32(netmask);
+}
+
+/**
+ * Convert a 16-bit range to a WFP condition
+ */
+static void range2cond(FWPM_FILTER_CONDITION0 *cond,
+					   u_int16_t from, u_int16_t to)
+{
+	if (from == to)
+	{
+		cond->matchType = FWP_MATCH_EQUAL;
+		cond->conditionValue.type = FWP_UINT16;
+		cond->conditionValue.uint16 = from;
+	}
+	else
+	{
+		cond->matchType = FWP_MATCH_RANGE;
+		cond->conditionValue.type = FWP_RANGE_TYPE;
+		cond->conditionValue.rangeValue = calloc(1, sizeof(FWP_RANGE0));
+		cond->conditionValue.rangeValue->valueLow.type = FWP_UINT16;
+		cond->conditionValue.rangeValue->valueLow.uint16 = from;
+		cond->conditionValue.rangeValue->valueHigh.type = FWP_UINT16;
+		cond->conditionValue.rangeValue->valueHigh.uint16 = to;
+	}
+}
+
+/**
+ * (Re-)allocate filter conditions for given local or remote traffic selector
+ */
+static bool ts2condition(traffic_selector_t *ts, const GUID *target,
+						 FWPM_FILTER_CONDITION0 *conds[], int *count)
+{
+	FWPM_FILTER_CONDITION0 *cond;
+	FWP_BYTE_ARRAY16 *addr;
+	FWP_RANGE0 *range;
+	u_int16_t from_port, to_port;
+	void *from, *to;
+	u_int8_t proto;
+	host_t *net;
+	u_int8_t prefix;
+
+	from = ts->get_from_address(ts).ptr;
+	to = ts->get_to_address(ts).ptr;
+	from_port = ts->get_from_port(ts);
+	to_port = ts->get_to_port(ts);
+
+	cond = append_condition(conds, count);
+	cond->fieldKey = *target;
+	if (ts->is_host(ts, NULL))
+	{
+		cond->matchType = FWP_MATCH_EQUAL;
+		switch (ts->get_type(ts))
+		{
+			case TS_IPV4_ADDR_RANGE:
+				cond->conditionValue.type = FWP_UINT32;
+				cond->conditionValue.uint32 = untoh32(from);
+				break;
+			case TS_IPV6_ADDR_RANGE:
+				cond->conditionValue.type = FWP_BYTE_ARRAY16_TYPE;
+				cond->conditionValue.byteArray16 = addr = malloc(sizeof(*addr));
+				memcpy(addr, from, sizeof(*addr));
+				break;
+			default:
+				return FALSE;
+		}
+	}
+	else if (ts->to_subnet(ts, &net, &prefix))
+	{
+		FWP_V6_ADDR_AND_MASK *m6;
+		FWP_V4_ADDR_AND_MASK *m4;
+
+		cond->matchType = FWP_MATCH_EQUAL;
+		switch (net->get_family(net))
+		{
+			case AF_INET:
+				cond->conditionValue.type = FWP_V4_ADDR_MASK;
+				cond->conditionValue.v4AddrMask = m4 = calloc(1, sizeof(*m4));
+				m4->addr = untoh32(from);
+				m4->mask = prefix2mask(prefix);
+				break;
+			case AF_INET6:
+				cond->conditionValue.type = FWP_V6_ADDR_MASK;
+				cond->conditionValue.v6AddrMask = m6 = calloc(1, sizeof(*m6));
+				memcpy(m6->addr, from, sizeof(m6->addr));
+				m6->prefixLength = prefix;
+				break;
+			default:
+				net->destroy(net);
+				return FALSE;
+		}
+		net->destroy(net);
+	}
+	else
+	{
+		cond->matchType = FWP_MATCH_RANGE;
+		cond->conditionValue.type = FWP_RANGE_TYPE;
+		cond->conditionValue.rangeValue = range = calloc(1, sizeof(*range));
+		switch (ts->get_type(ts))
+		{
+			case TS_IPV4_ADDR_RANGE:
+				range->valueLow.type = FWP_UINT32;
+				range->valueLow.uint32 = untoh32(from);
+				range->valueHigh.type = FWP_UINT32;
+				range->valueHigh.uint32 = untoh32(to);
+				break;
+			case TS_IPV6_ADDR_RANGE:
+				range->valueLow.type = FWP_BYTE_ARRAY16_TYPE;
+				range->valueLow.byteArray16 = addr = malloc(sizeof(*addr));
+				memcpy(addr, from, sizeof(*addr));
+				range->valueHigh.type = FWP_BYTE_ARRAY16_TYPE;
+				range->valueHigh.byteArray16 = addr = malloc(sizeof(*addr));
+				memcpy(addr, to, sizeof(*addr));
+				break;
+			default:
+				return FALSE;
+		}
+	}
+
+	proto = ts->get_protocol(ts);
+	if (proto && target == &FWPM_CONDITION_IP_LOCAL_ADDRESS)
+	{
+		cond = append_condition(conds, count);
+		cond->fieldKey = FWPM_CONDITION_IP_PROTOCOL;
+		cond->matchType = FWP_MATCH_EQUAL;
+		cond->conditionValue.type = FWP_UINT8;
+		cond->conditionValue.uint8 = proto;
+	}
+
+	if (proto == IPPROTO_ICMP)
+	{
+		if (target == &FWPM_CONDITION_IP_LOCAL_ADDRESS)
+		{
+			u_int8_t from_type, to_type, from_code, to_code;
+
+			from_type = traffic_selector_icmp_type(from_port);
+			to_type = traffic_selector_icmp_type(to_port);
+			from_code = traffic_selector_icmp_code(from_port);
+			to_code = traffic_selector_icmp_code(to_port);
+
+			if (from_type != 0 || to_type != 0xFF)
+			{
+				cond = append_condition(conds, count);
+				cond->fieldKey = FWPM_CONDITION_ICMP_TYPE;
+				range2cond(cond, from_type, to_type);
+			}
+			if (from_code != 0 || to_code != 0xFF)
+			{
+				cond = append_condition(conds, count);
+				cond->fieldKey = FWPM_CONDITION_ICMP_CODE;
+				range2cond(cond, from_code, to_code);
+			}
+		}
+	}
+	else if (from_port != 0 || to_port != 0xFFFF)
+	{
+		if (target == &FWPM_CONDITION_IP_LOCAL_ADDRESS)
+		{
+			cond = append_condition(conds, count);
+			cond->fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
+			range2cond(cond, from_port, to_port);
+		}
+		if (target == &FWPM_CONDITION_IP_REMOTE_ADDRESS)
+		{
+			cond = append_condition(conds, count);
+			cond->fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
+			range2cond(cond, from_port, to_port);
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * Free memory associated to a single condition
+ */
+static void free_condition(FWP_DATA_TYPE type, void *value)
+{
+	FWP_RANGE0 *range;
+
+	switch (type)
+	{
+		case FWP_BYTE_ARRAY16_TYPE:
+		case FWP_V4_ADDR_MASK:
+		case FWP_V6_ADDR_MASK:
+			free(value);
+			break;
+		case FWP_RANGE_TYPE:
+			range = value;
+			free_condition(range->valueLow.type, range->valueLow.sd);
+			free_condition(range->valueHigh.type, range->valueHigh.sd);
+			free(range);
+			break;
+		default:
+			break;
+	}
+}
+
+/**
+ * Free memory used by a set of conditions
+ */
+static void free_conditions(FWPM_FILTER_CONDITION0 *conds, int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++)
+	{
+		free_condition(conds[i].conditionValue.type, conds[i].conditionValue.sd);
+	}
+	free(conds);
+}
+
+/**
+ * Find the callout GUID for given parameters
+ */
+static bool find_callout(bool tunnel, bool v6, bool inbound, bool forward,
+						 GUID *layer, GUID *sublayer, GUID *callout)
+{
+	struct {
+		bool tunnel;
+		bool v6;
+		bool inbound;
+		bool forward;
+		const GUID *layer;
+		const GUID *sublayer;
+		const GUID *callout;
+	} map[] = {
+		{ 0, 0, 0, 0, 	&FWPM_LAYER_OUTBOUND_TRANSPORT_V4, NULL,
+						&FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4			},
+		{ 0, 0, 1, 0,	&FWPM_LAYER_INBOUND_TRANSPORT_V4, NULL,
+						&FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4			},
+		{ 0, 1, 0, 0,	&FWPM_LAYER_OUTBOUND_TRANSPORT_V6, NULL,
+						&FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6			},
+		{ 0, 1, 1, 0,	&FWPM_LAYER_INBOUND_TRANSPORT_V6, NULL,
+						&FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6			},
+		{ 1, 0, 0, 0,	&FWPM_LAYER_OUTBOUND_TRANSPORT_V4,
+						&FWPM_SUBLAYER_IPSEC_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4				},
+		{ 1, 0, 0, 1,	&FWPM_LAYER_IPFORWARD_V4,
+						&FWPM_SUBLAYER_IPSEC_FORWARD_OUTBOUND_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4		},
+		{ 1, 0, 1, 0,	&FWPM_LAYER_INBOUND_TRANSPORT_V4,
+						&FWPM_SUBLAYER_IPSEC_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4				},
+		{ 1, 0, 1, 1,	&FWPM_LAYER_IPFORWARD_V4,
+						&FWPM_SUBLAYER_IPSEC_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4		},
+		{ 1, 1, 0, 0,	&FWPM_LAYER_OUTBOUND_TRANSPORT_V6,
+						&FWPM_SUBLAYER_IPSEC_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6				},
+		{ 1, 1, 0, 1,	&FWPM_LAYER_IPFORWARD_V6,
+						&FWPM_SUBLAYER_IPSEC_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6		},
+		{ 1, 1, 1, 0,	&FWPM_LAYER_INBOUND_TRANSPORT_V6,
+						&FWPM_SUBLAYER_IPSEC_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6				},
+		{ 1, 1, 1, 1,	&FWPM_LAYER_IPFORWARD_V6,
+						&FWPM_SUBLAYER_IPSEC_TUNNEL,
+						&FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6		},
+	};
+	int i;
+
+	for (i = 0; i < countof(map); i++)
+	{
+		if (tunnel == map[i].tunnel &&
+			v6 == map[i].v6 &&
+			inbound == map[i].inbound &&
+			forward == map[i].forward)
+		{
+			*callout = *map[i].callout;
+			*layer = *map[i].layer;
+			if (map[i].sublayer)
+			{
+				*sublayer = *map[i].sublayer;
+			}
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Install a single policy in to the kernel
+ */
+static bool install_sp(private_kernel_wfp_ipsec_t *this, sp_entry_t *sp,
+					   GUID *context, bool inbound, bool fwd, UINT64 *filter_id)
+{
+	FWPM_FILTER_CONDITION0 *conds = NULL;
+	traffic_selector_t *local, *remote;
+	const GUID *ltarget, *rtarget;
+	int count = 0;
+	bool v6;
+	DWORD res;
+	FWPM_FILTER0 filter = {
+		.displayData = {
+			.name = L"charon IPsec policy",
+		},
+		.action = {
+			.type = FWP_ACTION_CALLOUT_TERMINATING,
+		},
+	};
+
+	if (context)
+	{
+		filter.flags |= FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT;
+		filter.providerKey = (GUID*)&this->provider.providerKey;
+		filter.providerContextKey = *context;
+	}
+
+	v6 = sp->src->get_type(sp->src) == TS_IPV6_ADDR_RANGE;
+	if (!find_callout(context != NULL, v6, inbound, fwd,
+					  &filter.layerKey, &filter.subLayerKey,
+					  &filter.action.calloutKey))
+	{
+		return FALSE;
+	}
+
+	if (inbound && fwd)
+	{
+		local = sp->dst;
+		remote = sp->src;
+	}
+	else
+	{
+		local = sp->src;
+		remote = sp->dst;
+	}
+	if (fwd)
+	{
+		ltarget = &FWPM_CONDITION_IP_SOURCE_ADDRESS;
+		rtarget = &FWPM_CONDITION_IP_DESTINATION_ADDRESS;
+	}
+	else
+	{
+		ltarget = &FWPM_CONDITION_IP_LOCAL_ADDRESS;
+		rtarget = &FWPM_CONDITION_IP_REMOTE_ADDRESS;
+	}
+	if (!ts2condition(local, ltarget, &conds, &count) ||
+		!ts2condition(remote, rtarget, &conds, &count))
+	{
+		free_conditions(conds, count);
+		return FALSE;
+	}
+
+	filter.numFilterConditions = count;
+	filter.filterCondition = conds;
+
+	res = FwpmFilterAdd0(this->handle, &filter, NULL, filter_id);
+	free_conditions(conds, count);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "installing %s%sbound WFP filter failed: 0x%08x",
+			 fwd ? "forward " : "", inbound ? "in" : "out", res);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Install a set of policies in to the kernel
+ */
+static bool install_sps(private_kernel_wfp_ipsec_t *this,
+						entry_t *entry, GUID *context)
+{
+	enumerator_t *enumerator;
+	sp_entry_t *sp;
+
+	enumerator = array_create_enumerator(entry->sps);
+	while (enumerator->enumerate(enumerator, &sp))
+	{
+		/* inbound policy */
+		if (!install_sp(this, sp, context, TRUE, FALSE, &sp->policy_in))
+		{
+			enumerator->destroy(enumerator);
+			return FALSE;
+		}
+		/* outbound policy */
+		if (!install_sp(this, sp, context, FALSE, FALSE, &sp->policy_out))
+		{
+			enumerator->destroy(enumerator);
+			return FALSE;
+		}
+		if (context)
+		{
+			if (!sp->src->is_host(sp->src, entry->local) ||
+				!sp->dst->is_host(sp->dst, entry->remote))
+			{
+				/* inbound forward policy, from decapsulation */
+				if (!install_sp(this, sp, context,
+								TRUE, TRUE, &sp->policy_fwd_in))
+				{
+					enumerator->destroy(enumerator);
+					return FALSE;
+				}
+				/* outbound forward policy, to encapsulate */
+				if (!install_sp(this, sp, context,
+								FALSE, TRUE, &sp->policy_fwd_out))
+				{
+					enumerator->destroy(enumerator);
+					return FALSE;
+				}
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	return TRUE;
+}
+
+/**
+ * Convert a chunk_t to a WFP FWP_BYTE_BLOB
+ */
+static inline FWP_BYTE_BLOB chunk2blob(chunk_t chunk)
+{
+	return (FWP_BYTE_BLOB){
+		.size = chunk.len,
+		.data = chunk.ptr,
+	};
+}
+
+/**
+ * Convert an integrity_algorithm_t to a WFP IPSEC_AUTH_TRANFORM_ID0
+ */
+static bool alg2auth(integrity_algorithm_t alg,
+					 IPSEC_SA_AUTH_INFORMATION0 *info)
+{
+	struct {
+		integrity_algorithm_t alg;
+		IPSEC_AUTH_TRANSFORM_ID0 transform;
+	} map[] = {
+		{ AUTH_HMAC_MD5_96,			IPSEC_AUTH_TRANSFORM_ID_HMAC_MD5_96		},
+		{ AUTH_HMAC_SHA1_96,		IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96	},
+		{ AUTH_HMAC_SHA2_256_128,	IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_256_128},
+		{ AUTH_AES_128_GMAC,		IPSEC_AUTH_TRANSFORM_ID_GCM_AES_128		},
+		{ AUTH_AES_192_GMAC,		IPSEC_AUTH_TRANSFORM_ID_GCM_AES_192		},
+		{ AUTH_AES_256_GMAC,		IPSEC_AUTH_TRANSFORM_ID_GCM_AES_256		},
+	};
+	int i;
+
+	for (i = 0; i < countof(map); i++)
+	{
+		if (map[i].alg == alg)
+		{
+			info->authTransform.authTransformId = map[i].transform;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Convert an encryption_algorithm_t to a WFP IPSEC_CIPHER_TRANFORM_ID0
+ */
+static bool alg2cipher(encryption_algorithm_t alg, int keylen,
+					   IPSEC_SA_CIPHER_INFORMATION0 *info)
+{
+	struct {
+		encryption_algorithm_t alg;
+		int keylen;
+		IPSEC_CIPHER_TRANSFORM_ID0 transform;
+	} map[] = {
+		{ ENCR_DES,				 8, IPSEC_CIPHER_TRANSFORM_ID_CBC_DES		},
+		{ ENCR_3DES,			24, IPSEC_CIPHER_TRANSFORM_ID_CBC_3DES		},
+		{ ENCR_AES_CBC,			16, IPSEC_CIPHER_TRANSFORM_ID_AES_128		},
+		{ ENCR_AES_CBC,			24, IPSEC_CIPHER_TRANSFORM_ID_AES_192		},
+		{ ENCR_AES_CBC,			32, IPSEC_CIPHER_TRANSFORM_ID_AES_256		},
+		{ ENCR_AES_GCM_ICV16,	20, IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_128	},
+		{ ENCR_AES_GCM_ICV16,	28, IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_192	},
+		{ ENCR_AES_GCM_ICV16,	36, IPSEC_CIPHER_TRANSFORM_ID_GCM_AES_256	},
+	};
+	int i;
+
+	for (i = 0; i < countof(map); i++)
+	{
+		if (map[i].alg == alg && map[i].keylen == keylen)
+		{
+			info->cipherTransform.cipherTransformId = map[i].transform;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Get the integrity algorithm used for an AEAD transform
+ */
+static integrity_algorithm_t encr2integ(encryption_algorithm_t encr, int keylen)
+{
+	struct {
+		encryption_algorithm_t encr;
+		int keylen;
+		integrity_algorithm_t integ;
+	} map[] = {
+		{ ENCR_NULL_AUTH_AES_GMAC,		20, AUTH_AES_128_GMAC				},
+		{ ENCR_NULL_AUTH_AES_GMAC,		28, AUTH_AES_192_GMAC				},
+		{ ENCR_NULL_AUTH_AES_GMAC,		36, AUTH_AES_256_GMAC				},
+		{ ENCR_AES_GCM_ICV16,			20, AUTH_AES_128_GMAC				},
+		{ ENCR_AES_GCM_ICV16,			28, AUTH_AES_192_GMAC				},
+		{ ENCR_AES_GCM_ICV16,			36, AUTH_AES_256_GMAC				},
+	};
+	int i;
+
+	for (i = 0; i < countof(map); i++)
+	{
+		if (map[i].encr == encr && map[i].keylen == keylen)
+		{
+			return map[i].integ;
+		}
+	}
+	return AUTH_UNDEFINED;
+}
+
+/**
+ * Install a single SA
+ */
+static bool install_sa(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+					   bool inbound, sa_entry_t *sa, FWP_IP_VERSION version)
+{
+	IPSEC_SA_AUTH_AND_CIPHER_INFORMATION0 info = {};
+	IPSEC_SA0 ipsec = {
+		.spi = ntohl(sa->spi),
+	};
+	IPSEC_SA_BUNDLE0 bundle = {
+		.lifetime = {
+			.lifetimeSeconds = inbound ? entry->isa.lifetime
+									   : entry->osa.lifetime,
+		},
+		.saList = &ipsec,
+		.numSAs = 1,
+		.ipVersion = version,
+	};
+	struct {
+		u_int16_t alg;
+		chunk_t key;
+	} integ = {}, encr = {};
+	DWORD res;
+
+	switch (sa->protocol)
+	{
+		case IPPROTO_AH:
+			ipsec.saTransformType = IPSEC_TRANSFORM_AH;
+			ipsec.ahInformation = &info.saAuthInformation;
+			integ.key = sa->integ.key;
+			integ.alg = sa->integ.alg;
+			break;
+		case IPPROTO_ESP:
+			if (sa->encr.alg == ENCR_NULL ||
+				sa->encr.alg == ENCR_NULL_AUTH_AES_GMAC)
+			{
+				ipsec.saTransformType = IPSEC_TRANSFORM_ESP_AUTH;
+				ipsec.espAuthInformation = &info.saAuthInformation;
+			}
+			else
+			{
+				ipsec.saTransformType = IPSEC_TRANSFORM_ESP_AUTH_AND_CIPHER;
+				ipsec.espAuthAndCipherInformation = &info;
+				encr.key = sa->encr.key;
+				encr.alg = sa->encr.alg;
+			}
+			if (encryption_algorithm_is_aead(sa->encr.alg))
+			{
+				integ.alg = encr2integ(sa->encr.alg, sa->encr.key.len);
+				integ.key = sa->encr.key;
+			}
+			else
+			{
+				integ.alg = sa->integ.alg;
+				integ.key = sa->integ.key;
+			}
+			break;
+		default:
+			return FALSE;
+	}
+
+	if (integ.alg)
+	{
+		info.saAuthInformation.authKey = chunk2blob(integ.key);
+		if (!alg2auth(integ.alg, &info.saAuthInformation))
+		{
+			DBG1(DBG_KNL, "integrity algorithm %N not supported by WFP",
+				 integrity_algorithm_names, integ.alg);
+			return FALSE;
+		}
+	}
+	if (encr.alg)
+	{
+		info.saCipherInformation.cipherKey = chunk2blob(encr.key);
+		if (!alg2cipher(encr.alg, encr.key.len, &info.saCipherInformation))
+		{
+			DBG1(DBG_KNL, "encryption algorithm %N not supported by WFP",
+				 encryption_algorithm_names, encr.alg);
+			return FALSE;
+		}
+	}
+
+	if (inbound)
+	{
+		res = IPsecSaContextAddInbound0(this->handle, entry->sa_id, &bundle);
+	}
+	else
+	{
+		bundle.flags |= IPSEC_SA_BUNDLE_FLAG_ASSUME_UDP_CONTEXT_OUTBOUND;
+		res = IPsecSaContextAddOutbound0(this->handle, entry->sa_id, &bundle);
+	}
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "adding %sbound WFP SA failed: 0x%08x",
+			 inbound ? "in" : "out", res);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Convert an IPv6 host address to WFP representation
+ */
+static void host2address6(host_t *host, void *out)
+{
+	u_int32_t *src, *dst = out;
+
+	src = (u_int32_t*)host->get_address(host).ptr;
+
+	dst[0] = untoh32(&src[3]);
+	dst[1] = untoh32(&src[2]);
+	dst[2] = untoh32(&src[1]);
+	dst[3] = untoh32(&src[0]);
+}
+
+/**
+ * Fill in traffic structure from entry addresses
+ */
+static bool hosts2traffic(private_kernel_wfp_ipsec_t *this,
+						  host_t *l, host_t *r, IPSEC_TRAFFIC1 *traffic)
+{
+	if (l->get_family(l) != r->get_family(r))
+	{
+		return FALSE;
+	}
+	switch (l->get_family(l))
+	{
+		case AF_INET:
+			traffic->ipVersion = FWP_IP_VERSION_V4;
+			traffic->localV4Address = untoh32(l->get_address(l).ptr);
+			traffic->remoteV4Address = untoh32(r->get_address(r).ptr);
+			return TRUE;
+		case AF_INET6:
+			traffic->ipVersion = FWP_IP_VERSION_V6;
+			host2address6(l, &traffic->localV6Address);
+			host2address6(r, &traffic->remoteV6Address);
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
+
+/**
+ * Install SAs to the kernel
+ */
+static bool install_sas(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+						IPSEC_TRAFFIC_TYPE type)
+{
+	IPSEC_TRAFFIC1 traffic = {
+		.trafficType = type,
+	};
+	IPSEC_GETSPI1 spi = {
+		.inboundIpsecTraffic = {
+			.trafficType = type,
+		},
+	};
+	enumerator_t *enumerator;
+	sp_entry_t *sp;
+	DWORD res;
+
+	if (type == IPSEC_TRAFFIC_TYPE_TRANSPORT)
+	{
+		enumerator = array_create_enumerator(entry->sps);
+		if (enumerator->enumerate(enumerator, &sp))
+		{
+			traffic.ipsecFilterId = sp->policy_out;
+			spi.inboundIpsecTraffic.ipsecFilterId = sp->policy_in;
+		}
+		else
+		{
+			enumerator->destroy(enumerator);
+			return FALSE;
+		}
+		enumerator->destroy(enumerator);
+	}
+	else
+	{
+		traffic.tunnelPolicyId = entry->provider;
+		spi.inboundIpsecTraffic.tunnelPolicyId = entry->provider;
+	}
+
+	if (!hosts2traffic(this, entry->local, entry->remote, &traffic))
+	{
+		return FALSE;
+	}
+
+	res = IPsecSaContextCreate1(this->handle, &traffic, NULL, NULL,
+								&entry->sa_id);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "creating WFP SA context failed: 0x%08x", res);
+		return FALSE;
+	}
+
+	memcpy(spi.inboundIpsecTraffic.localV6Address, traffic.localV6Address,
+		   sizeof(traffic.localV6Address));
+	memcpy(spi.inboundIpsecTraffic.remoteV6Address, traffic.remoteV6Address,
+		   sizeof(traffic.remoteV6Address));
+	spi.ipVersion = traffic.ipVersion;
+
+	res = IPsecSaContextSetSpi0(this->handle, entry->sa_id, &spi,
+								ntohl(entry->isa.spi));
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "setting WFP SA SPI failed: 0x%08x", res);
+		IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+		entry->sa_id = 0;
+		return FALSE;
+	}
+
+	if (!install_sa(this, entry, TRUE, &entry->isa, spi.ipVersion) ||
+		!install_sa(this, entry, FALSE, &entry->osa, spi.ipVersion))
+	{
+		IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+		entry->sa_id = 0;
+		return FALSE;
+	}
+
+	if (entry->encap)
+	{
+		IPSEC_V4_UDP_ENCAPSULATION0 encap = {
+			.localUdpEncapPort = entry->local->get_port(entry->local),
+			.remoteUdpEncapPort = entry->remote->get_port(entry->remote),
+		};
+		IPSEC_SA_CONTEXT1 *ctx;
+
+		res = IPsecSaContextGetById1(this->handle, entry->sa_id, &ctx);
+		if (res != ERROR_SUCCESS)
+		{
+			DBG1(DBG_KNL, "getting WFP SA for UDP encap failed: 0x%08x", res);
+			IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+			entry->sa_id = 0;
+			return FALSE;
+		}
+		ctx->inboundSa->udpEncapsulation = &encap;
+		ctx->outboundSa->udpEncapsulation = &encap;
+
+		res = IPsecSaContextUpdate0(this->handle,
+								IPSEC_SA_DETAILS_UPDATE_UDP_ENCAPSULATION, ctx);
+		FwpmFreeMemory0((void**)&ctx);
+		if (res != ERROR_SUCCESS)
+		{
+			DBG1(DBG_KNL, "enable WFP UDP encap failed: 0x%08x", res);
+			IPsecSaContextDeleteById0(this->handle, entry->sa_id);
+			entry->sa_id = 0;
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+/**
+ * Install a transport mode SA/SP set to the kernel
+ */
+static bool install_transport(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+	if (install_sps(this, entry, NULL) &&
+		install_sas(this, entry, IPSEC_TRAFFIC_TYPE_TRANSPORT))
+	{
+		return TRUE;
+	}
+	cleanup_policies(this, entry);
+	return FALSE;
+}
+
+/**
+ * Generate a new GUID, random
+ */
+static bool generate_guid(private_kernel_wfp_ipsec_t *this, GUID *guid)
+{
+	bool ok;
+	rng_t *rng;
+
+	rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+	if (!rng)
+	{
+		return FALSE;
+	}
+	ok = rng->get_bytes(rng, sizeof(GUID), (u_int8_t*)guid);
+	rng->destroy(rng);
+	return ok;
+}
+
+/**
+ * Register a dummy tunnel provider to associate tunnel filters to
+ */
+static bool add_tunnel_provider(private_kernel_wfp_ipsec_t *this,
+								entry_t *entry, GUID *guid, UINT64 *luid)
+{
+	DWORD res;
+
+	IPSEC_AUTH_TRANSFORM0 transform = {
+		/* Create any valid proposal. This is actually not used, as we
+		 * don't create an SA from this information. */
+		.authTransformId = IPSEC_AUTH_TRANSFORM_ID_HMAC_SHA_1_96,
+	};
+	IPSEC_SA_TRANSFORM0 transforms = {
+		.ipsecTransformType = IPSEC_TRANSFORM_ESP_AUTH,
+		.espAuthTransform = &transform,
+	};
+	IPSEC_PROPOSAL0 proposal = {
+		.lifetime = {
+			/* We need a valid lifetime, even if we don't create any SA
+			 * from these values. Pick some values accepted. */
+			.lifetimeSeconds = 0xFFFF,
+			.lifetimeKilobytes = 0xFFFFFFFF,
+			.lifetimePackets = 0xFFFFFFFF,
+		},
+		.numSaTransforms = 1,
+		.saTransforms = &transforms,
+	};
+	IPSEC_TUNNEL_POLICY0 policy = {
+		.numIpsecProposals = 1,
+		.ipsecProposals = &proposal,
+		.saIdleTimeout = {
+			/* not used, set to lifetime for maximum */
+			.idleTimeoutSeconds = proposal.lifetime.lifetimeSeconds,
+			.idleTimeoutSecondsFailOver = proposal.lifetime.lifetimeSeconds,
+		},
+	};
+	FWPM_PROVIDER_CONTEXT0 qm = {
+		.displayData = {
+			.name = L"charon tunnel provider",
+		},
+		.providerKey = (GUID*)&this->provider.providerKey,
+		.type = FWPM_IPSEC_IKE_QM_TUNNEL_CONTEXT,
+		.ikeQmTunnelPolicy = &policy,
+	};
+
+	switch (entry->local->get_family(entry->local))
+	{
+		case AF_INET:
+			policy.tunnelEndpoints.ipVersion = FWP_IP_VERSION_V4;
+			policy.tunnelEndpoints.localV4Address =
+						untoh32(entry->local->get_address(entry->local).ptr);
+			policy.tunnelEndpoints.remoteV4Address =
+						untoh32(entry->remote->get_address(entry->remote).ptr);
+			break;
+		case AF_INET6:
+			policy.tunnelEndpoints.ipVersion = FWP_IP_VERSION_V6;
+			host2address6(entry->local, &policy.tunnelEndpoints.localV6Address);
+			host2address6(entry->remote, &policy.tunnelEndpoints.remoteV6Address);
+			break;
+		default:
+			return FALSE;
+	}
+
+	if (!generate_guid(this, &qm.providerContextKey))
+	{
+		return FALSE;
+	}
+
+	res = FwpmProviderContextAdd0(this->handle, &qm, NULL, luid);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "adding provider context failed: 0x%08x", res);
+		return FALSE;
+	}
+	*guid = qm.providerContextKey;
+	return TRUE;
+}
+
+/**
+ * Install tunnel mode SPs to the kernel
+ */
+static bool install_tunnel_sps(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+	GUID guid;
+
+	if (!add_tunnel_provider(this, entry, &guid, &entry->provider))
+	{
+		return FALSE;
+	}
+	if (!install_sps(this, entry, &guid))
+	{
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Reduce refcount, or uninstall a route if all refs gone
+ */
+static bool uninstall_route(private_kernel_wfp_ipsec_t *this,
+							host_t *dst, u_int8_t mask, host_t *src, host_t *gtw)
+{
+	route_t *route, key = {
+		.dst = dst,
+		.mask = mask,
+		.src = src,
+	};
+	char *name;
+	bool res = FALSE;
+
+	this->mutex->lock(this->mutex);
+	route = this->routes->get(this->routes, &key);
+	if (route)
+	{
+		if (--route->refs == 0)
+		{
+			if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
+													   src, &name))
+			{
+				res = hydra->kernel_interface->del_route(hydra->kernel_interface,
+						dst->get_address(dst), mask, gtw, src, name) == SUCCESS;
+				free(name);
+			}
+			route = this->routes->remove(this->routes, route);
+			if (route)
+			{
+				destroy_route(route);
+			}
+		}
+		else
+		{
+			res = TRUE;
+		}
+	}
+	this->mutex->unlock(this->mutex);
+
+	return res;
+}
+
+/**
+ * Install a single route, or refcount if exists
+ */
+static bool install_route(private_kernel_wfp_ipsec_t *this,
+						  host_t *dst, u_int8_t mask, host_t *src, host_t *gtw)
+{
+	route_t *route, key = {
+		.dst = dst,
+		.mask = mask,
+		.src = src,
+	};
+	char *name;
+	bool res = FALSE;
+
+	this->mutex->lock(this->mutex);
+	route = this->routes->get(this->routes, &key);
+	if (route)
+	{
+		route->refs++;
+		res = TRUE;
+	}
+	else
+	{
+		if (hydra->kernel_interface->get_interface(hydra->kernel_interface,
+												   src, &name))
+		{
+			if (hydra->kernel_interface->add_route(hydra->kernel_interface,
+						dst->get_address(dst), mask, gtw, src, name) == SUCCESS)
+			{
+				INIT(route,
+					.dst = dst->clone(dst),
+					.mask = mask,
+					.src = src->clone(src),
+					.gtw = gtw ? gtw->clone(gtw) : NULL,
+					.refs = 1,
+				);
+				route = this->routes->put(this->routes, route, route);
+				if (route)
+				{
+					destroy_route(route);
+				}
+				res = TRUE;
+			}
+			free(name);
+		}
+	}
+	this->mutex->unlock(this->mutex);
+
+	return res;
+}
+
+/**
+ * (Un)-install a single route
+ */
+static bool manage_route(private_kernel_wfp_ipsec_t *this,
+						 host_t *local, host_t *remote,
+						 traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
+						 bool add)
+{
+	host_t *src, *dst, *gtw;
+	u_int8_t mask;
+	bool done;
+
+	if (!dst_ts->to_subnet(dst_ts, &dst, &mask))
+	{
+		return FALSE;
+	}
+	if (hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
+												src_ts, &src, NULL) != SUCCESS)
+	{
+		dst->destroy(dst);
+		return FALSE;
+	}
+	gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
+											   remote, -1, local);
+	if (add)
+	{
+		done = install_route(this, dst, mask, src, gtw);
+	}
+	else
+	{
+		done = uninstall_route(this, dst, mask, src, gtw);
+	}
+	dst->destroy(dst);
+	src->destroy(src);
+	DESTROY_IF(gtw);
+
+	if (!done)
+	{
+		DBG1(DBG_KNL, "%sinstalling route for policy %R === %R failed",
+			 add ? "" : "un", src_ts, dst_ts);
+	}
+	return done;
+}
+
+/**
+ * (Un)-install routes for IPsec policies
+ */
+static bool manage_routes(private_kernel_wfp_ipsec_t *this, entry_t *entry,
+						  bool add)
+{
+	enumerator_t *enumerator;
+	sp_entry_t *sp;
+
+	enumerator = array_create_enumerator(entry->sps);
+	while (enumerator->enumerate(enumerator, &sp))
+	{
+		if (add && sp->route)
+		{
+			continue;
+		}
+		if (!add && !sp->route)
+		{
+			continue;
+		}
+		if (manage_route(this, entry->local, entry->remote,
+						 sp->src, sp->dst, add))
+		{
+			sp->route = add;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	return TRUE;
+}
+
+/**
+ * Install a tunnel mode SA/SP set to the kernel
+ */
+static bool install_tunnel(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+	if (install_tunnel_sps(this, entry) &&
+		manage_routes(this, entry, TRUE) &&
+		install_sas(this, entry, IPSEC_TRAFFIC_TYPE_TUNNEL))
+	{
+		return TRUE;
+	}
+	cleanup_policies(this, entry);
+	return FALSE;
+}
+
+/**
+ * Install a SA/SP set to the kernel
+ */
+static bool install(private_kernel_wfp_ipsec_t *this, entry_t *entry)
+{
+	switch (entry->mode)
+	{
+		case MODE_TRANSPORT:
+			return install_transport(this, entry);
+		case MODE_TUNNEL:
+			return install_tunnel(this, entry);
+		case MODE_BEET:
+		default:
+			return FALSE;
+	}
+}
+
+/**
+ * Installed trap entry
+ */
+typedef struct {
+	/** reqid this trap is installed for */
+	u_int32_t reqid;
+	/** is this a forward policy trap for tunnel mode? */
+	bool fwd;
+	/** do we have installed a route for this trap policy? */
+	bool route;
+	/** local address of associated route */
+	host_t *local;
+	/** remote address of associated route */
+	host_t *remote;
+	/** src traffic selector */
+	traffic_selector_t *src;
+	/** dst traffic selector */
+	traffic_selector_t *dst;
+	/** LUID of installed tunnel policy filter */
+	UINT64 filter_id;
+} trap_t;
+
+/**
+ * Destroy a trap entry
+ */
+static void destroy_trap(trap_t *this)
+{
+	this->local->destroy(this->local);
+	this->remote->destroy(this->remote);
+	this->src->destroy(this->src);
+	this->dst->destroy(this->dst);
+	free(this);
+}
+
+/**
+ * Hashtable equals function for traps
+ */
+static bool equals_trap(trap_t *a, trap_t *b)
+{
+	return a->filter_id == b->filter_id;
+}
+
+/**
+ * Hashtable hash function for traps
+ */
+static u_int hash_trap(trap_t *trap)
+{
+	return chunk_hash(chunk_from_thing(trap->filter_id));
+}
+
+/**
+ * Send an acquire for an installed trap filter
+ */
+static void acquire(private_kernel_wfp_ipsec_t *this, UINT64 filter_id,
+					traffic_selector_t *src, traffic_selector_t *dst)
+{
+	u_int32_t reqid = 0;
+	trap_t *trap, key = {
+		.filter_id = filter_id,
+	};
+
+	this->mutex->lock(this->mutex);
+	trap = this->traps->get(this->traps, &key);
+	if (trap)
+	{
+		reqid = trap->reqid;
+	}
+	this->mutex->unlock(this->mutex);
+
+	if (reqid)
+	{
+		src = src ? src->clone(src) : NULL;
+		dst = dst ? dst->clone(dst) : NULL;
+		hydra->kernel_interface->acquire(hydra->kernel_interface, reqid,
+										 src, dst);
+	}
+}
+
+/**
+ * Create a single host traffic selector from an FWP address definition
+ */
+static traffic_selector_t *addr2ts(FWP_IP_VERSION version, void *data,
+					u_int8_t protocol, u_int16_t from_port, u_int16_t to_port)
+{
+	ts_type_t type;
+	UINT32 ints[4];
+	chunk_t addr;
+
+	switch (version)
+	{
+		case FWP_IP_VERSION_V4:
+			ints[0] = untoh32(data);
+			addr = chunk_from_thing(ints[0]);
+			type = TS_IPV4_ADDR_RANGE;
+			break;
+		case FWP_IP_VERSION_V6:
+			ints[3] = untoh32(data);
+			ints[2] = untoh32(data + 4);
+			ints[1] = untoh32(data + 8);
+			ints[0] = untoh32(data + 12);
+			addr = chunk_from_thing(ints);
+			type = TS_IPV6_ADDR_RANGE;
+			break;
+		default:
+			return NULL;
+	}
+	return traffic_selector_create_from_bytes(protocol, type, addr, from_port,
+											  addr, to_port);
+}
+
+/**
+ * FwpmNetEventSubscribe0() callback
+ */
+static void WINAPI event_callback(void *user, const FWPM_NET_EVENT1 *event)
+{
+	private_kernel_wfp_ipsec_t *this = user;
+	traffic_selector_t *local = NULL, *remote = NULL;
+	u_int8_t protocol = 0;
+	u_int16_t from_local = 0, to_local = 65535;
+	u_int16_t from_remote = 0, to_remote = 65535;
+
+	if ((event->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) &&
+		(event->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET))
+	{
+		if (event->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET)
+		{
+			from_local = to_local = event->header.localPort;
+		}
+		if (event->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET)
+		{
+			from_remote = to_remote = event->header.remotePort;
+		}
+		if (event->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET)
+		{
+			protocol = event->header.ipProtocol;
+		}
+
+		local = addr2ts(event->header.ipVersion,
+						(void*)&event->header.localAddrV6,
+						protocol, from_local, to_local);
+		remote = addr2ts(event->header.ipVersion,
+						(void*)&event->header.remoteAddrV6,
+						protocol, from_remote, to_remote);
+	}
+
+	switch (event->type)
+	{
+		case FWPM_NET_EVENT_TYPE_CLASSIFY_DROP:
+			acquire(this, event->classifyDrop->filterId, local, remote);
+			break;
+		case FWPM_NET_EVENT_TYPE_IKEEXT_MM_FAILURE:
+		case FWPM_NET_EVENT_TYPE_IKEEXT_QM_FAILURE:
+		case FWPM_NET_EVENT_TYPE_IKEEXT_EM_FAILURE:
+		case FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP:
+			DBG1(DBG_KNL, "IPsec kernel drop: %R === %R, error 0x%08x, "
+				 "SPI 0x%08x, %s filterId %llu", local, remote,
+				 event->ipsecDrop->failureStatus, event->ipsecDrop->spi,
+				 event->ipsecDrop->direction ? "in" : "out",
+				 event->ipsecDrop->filterId);
+			break;
+		case FWPM_NET_EVENT_TYPE_IPSEC_DOSP_DROP:
+		default:
+			break;
+	}
+
+	DESTROY_IF(local);
+	DESTROY_IF(remote);
+}
+
+/**
+ * Register for net events
+ */
+static bool register_events(private_kernel_wfp_ipsec_t *this)
+{
+	FWPM_NET_EVENT_SUBSCRIPTION0 subscription = {};
+	DWORD res;
+
+	res = FwpmNetEventSubscribe0(this->handle, &subscription,
+								 event_callback, this, &this->event);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "registering for WFP events failed: 0x%08x", res);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Install a trap policy to kernel
+ */
+static bool install_trap(private_kernel_wfp_ipsec_t *this, trap_t *trap)
+{
+	FWPM_FILTER_CONDITION0 *conds = NULL;
+	int count = 0;
+	DWORD res;
+	const GUID *starget, *dtarget;
+	UINT64 weight = 0x000000000000ff00;
+	FWPM_FILTER0 filter = {
+		.displayData = {
+			.name = L"charon IPsec trap",
+		},
+		.action = {
+			.type = FWP_ACTION_BLOCK,
+		},
+		.weight = {
+			.type = FWP_UINT64,
+			.uint64 = &weight,
+		},
+	};
+
+	if (trap->fwd)
+	{
+		if (trap->src->get_type(trap->src) == TS_IPV4_ADDR_RANGE)
+		{
+			filter.layerKey = FWPM_LAYER_IPFORWARD_V4;
+		}
+		else
+		{
+			filter.layerKey = FWPM_LAYER_IPFORWARD_V6;
+		}
+		starget = &FWPM_CONDITION_IP_SOURCE_ADDRESS;
+		dtarget = &FWPM_CONDITION_IP_DESTINATION_ADDRESS;
+	}
+	else
+	{
+		if (trap->src->get_type(trap->src) == TS_IPV4_ADDR_RANGE)
+		{
+			filter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
+		}
+		else
+		{
+			filter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V6;
+		}
+		starget = &FWPM_CONDITION_IP_LOCAL_ADDRESS;
+		dtarget = &FWPM_CONDITION_IP_REMOTE_ADDRESS;
+	}
+
+	if (!ts2condition(trap->src, starget, &conds, &count) ||
+		!ts2condition(trap->dst, dtarget, &conds, &count))
+	{
+		free_conditions(conds, count);
+		return FALSE;
+	}
+
+	filter.numFilterConditions = count;
+	filter.filterCondition = conds;
+
+	res = FwpmFilterAdd0(this->handle, &filter, NULL, &trap->filter_id);
+	free_conditions(conds, count);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "installing WFP trap filter failed: 0x%08x", res);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Uninstall a trap policy from kernel
+ */
+static bool uninstall_trap(private_kernel_wfp_ipsec_t *this, trap_t *trap)
+{
+	DWORD res;
+
+	res = FwpmFilterDeleteById0(this->handle, trap->filter_id);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "uninstalling WFP trap filter failed: 0x%08x", res);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Create and install a new trap entry
+ */
+static bool add_trap(private_kernel_wfp_ipsec_t *this,
+					 u_int32_t reqid, bool fwd, host_t *local, host_t *remote,
+					 traffic_selector_t *src, traffic_selector_t *dst)
+{
+	trap_t *trap;
+
+	INIT(trap,
+		.reqid = reqid,
+		.fwd = fwd,
+		.src = src->clone(src),
+		.dst = dst->clone(dst),
+		.local = local->clone(local),
+		.remote = remote->clone(remote),
+	);
+
+	if (!install_trap(this, trap))
+	{
+		destroy_trap(trap);
+		return FALSE;
+	}
+
+	trap->route = manage_route(this, local, remote, src, dst, TRUE);
+
+	this->mutex->lock(this->mutex);
+	this->traps->put(this->traps, trap, trap);
+	this->mutex->unlock(this->mutex);
+	return TRUE;
+}
+
+/**
+ * Uninstall and remove a new trap entry
+ */
+static bool remove_trap(private_kernel_wfp_ipsec_t *this,
+						u_int32_t reqid, bool fwd,
+						traffic_selector_t *src, traffic_selector_t *dst)
+{
+	enumerator_t *enumerator;
+	trap_t *trap, *found = NULL;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->traps->create_enumerator(this->traps);
+	while (enumerator->enumerate(enumerator, NULL, &trap))
+	{
+		if (reqid == trap->reqid &&
+			fwd == trap->fwd &&
+			src->equals(src, trap->src) &&
+			dst->equals(dst, trap->dst))
+		{
+			this->traps->remove_at(this->traps, enumerator);
+			found = trap;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+
+	if (found)
+	{
+		if (trap->route)
+		{
+			trap->route = !manage_route(this, trap->local, trap->remote,
+										src, dst, FALSE);
+		}
+		uninstall_trap(this, found);
+		destroy_trap(found);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
+	private_kernel_wfp_ipsec_t *this)
+{
+	return KERNEL_ESP_V3_TFC | KERNEL_NO_POLICY_UPDATES;
+}
+
+/**
+ * Initialize seeds for SPI generation
+ */
+static bool init_spi(private_kernel_wfp_ipsec_t *this)
+{
+	bool ok = TRUE;
+	rng_t *rng;
+
+	rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+	if (!rng)
+	{
+		return FALSE;
+	}
+	ok = rng->get_bytes(rng, sizeof(this->nextspi), (u_int8_t*)&this->nextspi);
+	if (ok)
+	{
+		ok = rng->get_bytes(rng, sizeof(this->mixspi), (u_int8_t*)&this->mixspi);
+	}
+	rng->destroy(rng);
+	return ok;
+}
+
+/**
+ * Map an integer x with a one-to-one function using quadratic residues.
+ */
+static u_int permute(u_int x, u_int p)
+{
+	u_int qr;
+
+	x = x % p;
+	qr = ((u_int64_t)x * x) % p;
+	if (x <= p / 2)
+	{
+		return qr;
+	}
+	return p - qr;
+}
+
+METHOD(kernel_ipsec_t, get_spi, status_t,
+	private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+	u_int8_t protocol, u_int32_t reqid, u_int32_t *spi)
+{
+	/* To avoid sequencial SPIs, we use a one-to-one permuation function on
+	 * an incrementing counter, that is a full period PRNG for the range we
+	 * allocate SPIs in. We add some randomness using a fixed XOR and start
+	 * the counter at random position. This is not cryptographically safe,
+	 * but that is actually not required.
+	 * The selected prime should be smaller than the range we allocate SPIs
+	 * in, and it must satisfy p % 4 == 3 to map x > p/2 using p - qr. */
+	static const u_int p = 268435399, offset = 0xc0000000;
+
+	*spi = htonl(offset + permute(ref_get(&this->nextspi) ^ this->mixspi, p));
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, get_cpi, status_t,
+	private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+	u_int32_t reqid, u_int16_t *cpi)
+{
+	return NOT_SUPPORTED;
+}
+
+/**
+ * Data for an expire callback job
+ */
+typedef struct {
+	/* backref to kernel backend */
+	private_kernel_wfp_ipsec_t *this;
+	/* SPI of expiring SA */
+	u_int32_t spi;
+	/* destination address of expiring SA */
+	host_t *dst;
+	/* is this a hard expire, or a rekey request? */
+	bool hard;
+} expire_data_t;
+
+/**
+ * Clean up expire data
+ */
+static void expire_data_destroy(expire_data_t *data)
+{
+	data->dst->destroy(data->dst);
+	free(data);
+}
+
+/**
+ * Callback job for SA expiration
+ */
+static job_requeue_t expire_job(expire_data_t *data)
+{
+	private_kernel_wfp_ipsec_t *this = data->this;
+	u_int32_t reqid = 0;
+	u_int8_t protocol;
+	entry_t *entry;
+	sa_entry_t key = {
+		.spi = data->spi,
+		.dst = data->dst,
+	};
+
+	if (data->hard)
+	{
+		this->mutex->lock(this->mutex);
+		entry = this->isas->remove(this->isas, &key);
+		this->mutex->unlock(this->mutex);
+		if (entry)
+		{
+			protocol = entry->isa.protocol;
+			reqid = entry->reqid;
+			if (entry->osa.dst)
+			{
+				key.dst = entry->osa.dst;
+				key.spi = entry->osa.spi;
+				this->osas->remove(this->osas, &key);
+			}
+			entry_destroy(this, entry);
+		}
+	}
+	else
+	{
+		this->mutex->lock(this->mutex);
+		entry = this->isas->get(this->isas, &key);
+		if (entry)
+		{
+			protocol = entry->isa.protocol;
+			reqid = entry->reqid;
+		}
+		this->mutex->unlock(this->mutex);
+	}
+
+	if (reqid)
+	{
+		hydra->kernel_interface->expire(hydra->kernel_interface,
+										reqid, protocol, data->spi, data->hard);
+	}
+
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Schedule an expire event for an SA
+ */
+static void schedule_expire(private_kernel_wfp_ipsec_t *this, u_int32_t spi,
+							host_t *dst, u_int32_t lifetime, bool hard)
+{
+	expire_data_t *data;
+
+	INIT(data,
+		.this = this,
+		.spi = spi,
+		.dst = dst->clone(dst),
+		.hard = hard,
+	);
+
+	lib->scheduler->schedule_job(lib->scheduler, (job_t*)
+						callback_job_create((void*)expire_job, data,
+											(void*)expire_data_destroy, NULL),
+						lifetime);
+}
+
+METHOD(kernel_ipsec_t, add_sa, status_t,
+	private_kernel_wfp_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,
+	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+{
+	host_t *local, *remote;
+	entry_t *entry;
+
+	if (inbound)
+	{
+		/* comes first, create new entry */
+		local = dst->clone(dst);
+		remote = src->clone(src);
+
+		INIT(entry,
+			.reqid = reqid,
+			.isa = {
+				.spi = spi,
+				.dst = local,
+				.protocol = protocol,
+				.lifetime = lifetime->time.life,
+				.encr = {
+					.alg = enc_alg,
+					.key = chunk_clone(enc_key),
+				},
+				.integ = {
+					.alg = int_alg,
+					.key = chunk_clone(int_key),
+				},
+			},
+			.sps = array_create(0, 0),
+			.local = local,
+			.remote = remote,
+			.mode = mode,
+			.encap = encap,
+		);
+
+		if (lifetime->time.life)
+		{
+			schedule_expire(this, spi, local, lifetime->time.life, TRUE);
+		}
+		if (lifetime->time.rekey && lifetime->time.rekey != lifetime->time.life)
+		{
+			schedule_expire(this, spi, local, lifetime->time.rekey, FALSE);
+		}
+
+		this->mutex->lock(this->mutex);
+		this->tsas->put(this->tsas, (void*)(uintptr_t)reqid, entry);
+		this->isas->put(this->isas, &entry->isa, entry);
+		this->mutex->unlock(this->mutex);
+	}
+	else
+	{
+		/* comes after inbound, update entry */
+		this->mutex->lock(this->mutex);
+		entry = this->tsas->remove(this->tsas, (void*)(uintptr_t)reqid);
+		this->mutex->unlock(this->mutex);
+
+		if (!entry)
+		{
+			DBG1(DBG_KNL, "adding outbound SA failed, no inbound SA found "
+				 "for reqid %u ", reqid);
+			return NOT_FOUND;
+		}
+		/* TODO: should we check for local/remote, mode etc.? */
+
+		entry->osa = (sa_entry_t){
+			.spi = spi,
+			.dst = entry->remote,
+			.protocol = protocol,
+			.lifetime = lifetime->time.life,
+			.encr = {
+				.alg = enc_alg,
+				.key = chunk_clone(enc_key),
+			},
+			.integ = {
+				.alg = int_alg,
+				.key = chunk_clone(int_key),
+			},
+		};
+
+		this->mutex->lock(this->mutex);
+		this->osas->put(this->osas, &entry->osa, entry);
+		this->mutex->unlock(this->mutex);
+	}
+
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, update_sa, status_t,
+	private_kernel_wfp_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)
+{
+	entry_t *entry;
+	sa_entry_t key = {
+		.dst = dst,
+		.spi = spi,
+	};
+	UINT64 sa_id = 0;
+	IPSEC_SA_CONTEXT1 *ctx;
+	IPSEC_V4_UDP_ENCAPSULATION0 ports;
+	UINT32 flags = IPSEC_SA_DETAILS_UPDATE_TRAFFIC;
+	DWORD res;
+
+	this->mutex->lock(this->mutex);
+	entry = this->osas->get(this->osas, &key);
+	this->mutex->unlock(this->mutex);
+
+	if (entry)
+	{
+		/* outbound entry, nothing to do */
+		return SUCCESS;
+	}
+
+	this->mutex->lock(this->mutex);
+	entry = this->isas->get(this->isas, &key);
+	if (entry)
+	{
+		/* inbound entry, do update */
+		sa_id = entry->sa_id;
+		ports.localUdpEncapPort = entry->local->get_port(entry->local);
+		ports.remoteUdpEncapPort = entry->remote->get_port(entry->remote);
+	}
+	this->mutex->unlock(this->mutex);
+
+	if (!sa_id)
+	{
+		return NOT_FOUND;
+	}
+
+	res = IPsecSaContextGetById1(this->handle, sa_id, &ctx);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "getting WFP SA context for updated failed: 0x%08x", res);
+		return FAILED;
+	}
+	if (!hosts2traffic(this, new_dst, new_src, &ctx->inboundSa->traffic) ||
+		!hosts2traffic(this, new_dst, new_src, &ctx->outboundSa->traffic))
+	{
+		FwpmFreeMemory0((void**)&ctx);
+		return FAILED;
+	}
+
+	if (new_encap != encap)
+	{
+		if (new_encap)
+		{
+			ctx->inboundSa->udpEncapsulation = &ports;
+			ctx->outboundSa->udpEncapsulation = &ports;
+		}
+		else
+		{
+			ctx->inboundSa->udpEncapsulation = NULL;
+			ctx->outboundSa->udpEncapsulation = NULL;
+		}
+		flags |= IPSEC_SA_DETAILS_UPDATE_UDP_ENCAPSULATION;
+	}
+
+	res = IPsecSaContextUpdate0(this->handle, flags, ctx);
+	FwpmFreeMemory0((void**)&ctx);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "updating WFP SA context failed: 0x%08x", res);
+		return FAILED;
+	}
+
+	this->mutex->lock(this->mutex);
+	entry = this->isas->remove(this->isas, &key);
+	if (entry)
+	{
+		key.spi = entry->osa.spi;
+		key.dst = entry->osa.dst;
+		this->osas->remove(this->osas, &key);
+
+		entry->local->destroy(entry->local);
+		entry->remote->destroy(entry->remote);
+		entry->local = new_dst->clone(new_dst);
+		entry->remote = new_src->clone(new_src);
+		entry->isa.dst = entry->local;
+		entry->osa.dst = entry->remote;
+
+		this->isas->put(this->isas, &entry->isa, entry);
+		this->osas->put(this->osas, &entry->osa, entry);
+
+		manage_routes(this, entry, FALSE);
+		manage_routes(this, entry, TRUE);
+	}
+	this->mutex->unlock(this->mutex);
+
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, query_sa, status_t,
+	private_kernel_wfp_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)
+{
+	/* It does not seem that WFP provides any means of getting per-SA traffic
+	 * statistics. IPsecGetStatistics0/1() provides global stats, and
+	 * IPsecSaContextEnum0/1() and IPsecSaEnum0/1() return the configured
+	 * values only. */
+	return NOT_SUPPORTED;
+}
+
+METHOD(kernel_ipsec_t, del_sa, status_t,
+	private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
+	u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
+{
+	entry_t *entry;
+	sa_entry_t key = {
+		.dst = dst,
+		.spi = spi,
+	};
+
+	this->mutex->lock(this->mutex);
+	entry = this->isas->remove(this->isas, &key);
+	this->mutex->unlock(this->mutex);
+
+	if (entry)
+	{
+		/* keep entry until removal of outbound */
+		return SUCCESS;
+	}
+
+	this->mutex->lock(this->mutex);
+	entry = this->osas->remove(this->osas, &key);
+	this->mutex->unlock(this->mutex);
+
+	if (entry)
+	{
+		entry_destroy(this, entry);
+		return SUCCESS;
+	}
+
+	return NOT_FOUND;
+}
+
+METHOD(kernel_ipsec_t, flush_sas, status_t,
+	private_kernel_wfp_ipsec_t *this)
+{
+	return NOT_SUPPORTED;
+}
+
+METHOD(kernel_ipsec_t, add_policy, status_t,
+	private_kernel_wfp_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)
+{
+	status_t status = SUCCESS;
+	entry_t *entry;
+	sp_entry_t *sp;
+	sa_entry_t key = {
+		.spi = sa->esp.use ? sa->esp.spi : sa->ah.spi,
+		.dst = dst,
+	};
+
+	if (sa->esp.use && sa->ah.use)
+	{
+		return NOT_SUPPORTED;
+	}
+
+	switch (type)
+	{
+		case POLICY_IPSEC:
+			break;
+		case POLICY_PASS:
+		case POLICY_DROP:
+			return NOT_SUPPORTED;
+	}
+
+	switch (direction)
+	{
+		case POLICY_OUT:
+			break;
+		case POLICY_IN:
+		case POLICY_FWD:
+			/* not required */
+			return SUCCESS;
+		default:
+			return NOT_SUPPORTED;
+	}
+
+	switch (priority)
+	{
+		case POLICY_PRIORITY_DEFAULT:
+			break;
+		case POLICY_PRIORITY_ROUTED:
+			if (!add_trap(this, sa->reqid, FALSE, src, dst, src_ts, dst_ts))
+			{
+				return FAILED;
+			}
+			if (sa->mode == MODE_TUNNEL)
+			{
+				if (!add_trap(this, sa->reqid, TRUE, src, dst, src_ts, dst_ts))
+				{
+					return FAILED;
+				}
+			}
+			return SUCCESS;
+		case POLICY_PRIORITY_FALLBACK:
+		default:
+			return NOT_SUPPORTED;
+	}
+
+	this->mutex->lock(this->mutex);
+	entry = this->osas->get(this->osas, &key);
+	if (entry)
+	{
+		if (sa->mode == MODE_TUNNEL || array_count(entry->sps) == 0)
+		{
+			INIT(sp,
+				.src = src_ts->clone(src_ts),
+				.dst = dst_ts->clone(dst_ts),
+			);
+			array_insert(entry->sps, -1, sp);
+			if (array_count(entry->sps) == sa->policy_count)
+			{
+				if (!install(this, entry))
+				{
+					status = FAILED;
+				}
+			}
+		}
+		else
+		{
+			/* TODO: reinstall with a filter using multiple TS?
+			 * Filters are ANDed for a match, but we could install a filter
+			 * with the inverse TS set using NOT-matches... */
+			DBG1(DBG_KNL, "multiple transport mode traffic selectors not "
+				 "supported by WFP");
+			status = NOT_SUPPORTED;
+		}
+	}
+	else
+	{
+		DBG1(DBG_KNL, "adding SP failed, no SA found for SPI 0x%08x", key.spi);
+		status = FAILED;
+	}
+	this->mutex->unlock(this->mutex);
+
+	return status;
+}
+
+METHOD(kernel_ipsec_t, query_policy, status_t,
+	private_kernel_wfp_ipsec_t *this, traffic_selector_t *src_ts,
+	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+	time_t *use_time)
+{
+	/* see query_sa() for some notes */
+	return NOT_SUPPORTED;
+}
+
+METHOD(kernel_ipsec_t, del_policy, status_t,
+	private_kernel_wfp_ipsec_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 priority)
+{
+	if (direction == POLICY_OUT && priority == POLICY_PRIORITY_ROUTED)
+	{
+		if (remove_trap(this, reqid, FALSE, src_ts, dst_ts))
+		{
+			remove_trap(this, reqid, TRUE, src_ts, dst_ts);
+			return SUCCESS;
+		}
+		return NOT_FOUND;
+	}
+	/* not required, as we delete the whole SA/SP set during del_sa() */
+	return SUCCESS;
+}
+
+METHOD(kernel_ipsec_t, flush_policies, status_t,
+	private_kernel_wfp_ipsec_t *this)
+{
+	return NOT_SUPPORTED;
+}
+
+/**
+ * Add a bypass policy for a specific UDP port
+ */
+static bool add_bypass(private_kernel_wfp_ipsec_t *this,
+					   int family, u_int16_t port, bool inbound, UINT64 *luid)
+{
+	FWPM_FILTER_CONDITION0 *cond, *conds = NULL;
+	int count = 0;
+	DWORD res;
+	UINT64 weight = 0xff00000000000000;
+	FWPM_FILTER0 filter = {
+		.displayData = {
+			.name = L"charon IKE bypass",
+		},
+		.action = {
+			.type = FWP_ACTION_PERMIT,
+		},
+		.weight = {
+			.type = FWP_UINT64,
+			.uint64 = &weight,
+		},
+	};
+
+	switch (family)
+	{
+		case AF_INET:
+			filter.layerKey = inbound ? FWPM_LAYER_INBOUND_TRANSPORT_V4
+									  : FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
+			break;
+		case AF_INET6:
+			filter.layerKey = inbound ? FWPM_LAYER_INBOUND_TRANSPORT_V6
+									  : FWPM_LAYER_OUTBOUND_TRANSPORT_V6;
+			break;
+		default:
+			return FALSE;
+	}
+
+	cond = append_condition(&conds, &count);
+	cond->fieldKey = FWPM_CONDITION_IP_PROTOCOL;
+	cond->matchType = FWP_MATCH_EQUAL;
+	cond->conditionValue.type = FWP_UINT8;
+	cond->conditionValue.uint8 = IPPROTO_UDP;
+
+	cond = append_condition(&conds, &count);
+	cond->fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
+	cond->matchType = FWP_MATCH_EQUAL;
+	cond->conditionValue.type = FWP_UINT16;
+	cond->conditionValue.uint16 = port;
+
+	filter.numFilterConditions = count;
+	filter.filterCondition = conds;
+
+	res = FwpmFilterAdd0(this->handle, &filter, NULL, luid);
+	free_conditions(conds, count);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "installing WFP bypass filter failed: 0x%08x", res);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+METHOD(kernel_ipsec_t, bypass_socket, bool,
+	private_kernel_wfp_ipsec_t *this, int fd, int family)
+{
+	union {
+		struct sockaddr sa;
+		SOCKADDR_IN in;
+		SOCKADDR_IN6 in6;
+	} saddr;
+	int addrlen = sizeof(saddr);
+	UINT64 filter_out, filter_in = 0;
+	u_int16_t port;
+
+	if (getsockname(fd, &saddr.sa, &addrlen) == SOCKET_ERROR)
+	{
+		return FALSE;
+	}
+	switch (family)
+	{
+		case AF_INET:
+			port = ntohs(saddr.in.sin_port);
+			break;
+		case AF_INET6:
+			port = ntohs(saddr.in6.sin6_port);
+			break;
+		default:
+			return FALSE;
+	}
+
+	if (!add_bypass(this, family, port, TRUE, &filter_in) ||
+		!add_bypass(this, family, port, FALSE, &filter_out))
+	{
+		if (filter_in)
+		{
+			FwpmFilterDeleteById0(this->handle, filter_in);
+		}
+		return FALSE;
+	}
+
+	this->mutex->lock(this->mutex);
+	array_insert(this->bypass, ARRAY_TAIL, &filter_in);
+	array_insert(this->bypass, ARRAY_TAIL, &filter_out);
+	this->mutex->unlock(this->mutex);
+
+	return TRUE;
+}
+
+METHOD(kernel_ipsec_t, enable_udp_decap, bool,
+	private_kernel_wfp_ipsec_t *this, int fd, int family, u_int16_t port)
+{
+	return FALSE;
+}
+
+METHOD(kernel_ipsec_t, destroy, void,
+	private_kernel_wfp_ipsec_t *this)
+{
+	UINT64 filter;
+
+	while (array_remove(this->bypass, ARRAY_TAIL, &filter))
+	{
+		FwpmFilterDeleteById0(this->handle, filter);
+	}
+	if (this->handle)
+	{
+		if (this->event)
+		{
+			FwpmNetEventUnsubscribe0(this->handle, this->event);
+		}
+		FwpmProviderDeleteByKey0(this->handle, &this->provider.providerKey);
+		FwpmEngineClose0(this->handle);
+	}
+	array_destroy(this->bypass);
+	this->tsas->destroy(this->tsas);
+	this->isas->destroy(this->isas);
+	this->osas->destroy(this->osas);
+	this->routes->destroy(this->routes);
+	this->traps->destroy(this->traps);
+	this->mutex->destroy(this->mutex);
+	free(this);
+}
+
+/*
+ * Described in header.
+ */
+kernel_wfp_ipsec_t *kernel_wfp_ipsec_create()
+{
+	private_kernel_wfp_ipsec_t *this;
+	DWORD res;
+	FWPM_SESSION0 session = {
+		.displayData = {
+			.name = L"charon",
+			.description = L"strongSwan IKE kernel-wfp backend",
+		},
+	};
+
+	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,
+			},
+		},
+		.provider = {
+			.displayData = {
+				.name = L"charon",
+				.description = L"strongSwan IKE kernel-wfp backend",
+			},
+			.providerKey = { 0x59cdae2e, 0xf6bb, 0x4c09,
+							{ 0xa9,0x59,0x9d,0x91,0xac,0xaf,0xf9,0x19 }},
+		},
+		.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
+		.bypass = array_create(sizeof(UINT64), 2),
+		.tsas = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4),
+		.isas = hashtable_create((void*)hash_sa, (void*)equals_sa, 4),
+		.osas = hashtable_create((void*)hash_sa, (void*)equals_sa, 4),
+		.routes = hashtable_create((void*)hash_route, (void*)equals_route, 4),
+		.traps = hashtable_create((void*)hash_trap, (void*)equals_trap, 4),
+	);
+
+	if (!init_spi(this))
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	res = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session,
+						  &this->handle);
+	if (res != ERROR_SUCCESS)
+	{
+		DBG1(DBG_KNL, "opening WFP engine failed: 0x%08x", res);
+		destroy(this);
+		return NULL;
+	}
+
+	res = FwpmProviderAdd0(this->handle, &this->provider, NULL);
+	if (res != ERROR_SUCCESS && res != FWP_E_ALREADY_EXISTS)
+	{
+		DBG1(DBG_KNL, "registering WFP provider failed: 0x%08x", res);
+		destroy(this);
+		return NULL;
+	}
+
+	if (!register_events(this))
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.h b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.h
new file mode 100644
index 0000000..d61c230
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_ipsec.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup kernel_wfp_ipsec kernel_wfp_ipsec
+ * @{ @ingroup kernel_wfp
+ */
+
+#ifndef KERNEL_WFP_IPSEC_H_
+#define KERNEL_WFP_IPSEC_H_
+
+#include <library.h>
+#include <kernel/kernel_ipsec.h>
+
+typedef struct kernel_wfp_ipsec_t kernel_wfp_ipsec_t;
+
+/**
+ * Windows Filter Platform based IPsec kernel backend.
+ */
+struct kernel_wfp_ipsec_t {
+
+	/**
+	 * Implements kernel_ipsec_t interface
+	 */
+	kernel_ipsec_t interface;
+};
+
+/**
+ * Create WFP kernel interface instance.
+ *
+ * @return			kernel_wfp_ipsec_t instance
+ */
+kernel_wfp_ipsec_t *kernel_wfp_ipsec_create();
+
+#endif /** KERNEL_WFP_IPSEC_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.c b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.c
new file mode 100644
index 0000000..e465b0a
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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_wfp_plugin.h"
+#include "kernel_wfp_ipsec.h"
+
+#include <daemon.h>
+
+typedef struct private_kernel_wfp_plugin_t private_kernel_wfp_plugin_t;
+
+/**
+ * Private data of kernel-wfp plugin
+ */
+struct private_kernel_wfp_plugin_t {
+
+	/**
+	 * Implements plugin interface
+	 */
+	kernel_wfp_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_kernel_wfp_plugin_t *this)
+{
+	return "kernel-wfp";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_kernel_wfp_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK(kernel_ipsec_register, kernel_wfp_ipsec_create),
+			PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
+				PLUGIN_DEPENDS(RNG, RNG_WEAK),
+				PLUGIN_DEPENDS(RNG, RNG_STRONG),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_kernel_wfp_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *kernel_wfp_plugin_create()
+{
+	private_kernel_wfp_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_wfp/kernel_wfp_plugin.h b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.h
new file mode 100644
index 0000000..a538e34
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/kernel_wfp_plugin.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup kernel_wfp kernel_wfp
+ * @ingroup cplugins
+ *
+ * @defgroup kernel_wfp_plugin kernel_wfp_plugin
+ * @{ @ingroup kernel_wfp
+ */
+
+#ifndef KERNEL_WFP_PLUGIN_H_
+#define KERNEL_WFP_PLUGIN_H_
+
+#include <library.h>
+#include <plugins/plugin.h>
+
+typedef struct kernel_wfp_plugin_t kernel_wfp_plugin_t;
+
+/**
+ * Windows Filter Platform based IPsec backend plugin.
+ */
+struct kernel_wfp_plugin_t {
+
+	/**
+	 * implements plugin interface
+	 */
+	plugin_t plugin;
+};
+
+#endif /** KERNEL_WFP_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/kernel_wfp/mingw-w64-4.8.1.diff b/src/libcharon/plugins/kernel_wfp/mingw-w64-4.8.1.diff
new file mode 100644
index 0000000..c72b94c
--- /dev/null
+++ b/src/libcharon/plugins/kernel_wfp/mingw-w64-4.8.1.diff
@@ -0,0 +1,26 @@
+diff -Naur /mingw-orig/x86_64-w64-mingw32/include/fwptypes.h /mingw/x86_64-w64-mingw32/include/fwptypes.h
+--- /mingw-orig/x86_64-w64-mingw32/include/fwptypes.h	2013-08-30 07:15:40 +0200
++++ /mingw/x86_64-w64-mingw32/include/fwptypes.h	2014-01-02 16:32:26 +0100
+@@ -333,11 +333,6 @@
+     } __C89_NAMELESSUNIONNAME;
+ } FWP_CONDITION_VALUE0;
+
+-typedef struct FWPM_DISPLAY_DATA0_ {
+-    wchar_t *name;
+-    wchar_t *description;
+-} FWPM_DISPLAY_DATA0;
+-
+ #endif /* WINAPI_PARTITION_DESKTOP. */
+ /* Begin additional prototypes for all interfaces */
+
+diff -Naur /mingw-orig/x86_64-w64-mingw32/include/iketypes.h /mingw/x86_64-w64-mingw32/include/iketypes.h
+--- /mingw-orig/x86_64-w64-mingw32/include/iketypes.h	2013-08-30 07:15:40 +0200
++++ /mingw/x86_64-w64-mingw32/include/iketypes.h	2014-01-02 16:31:12 +0100
+@@ -212,7 +212,6 @@
+     FWP_BYTE_BLOB presharedKey;
+     UINT32 flags;
+ } IKEEXT_PRESHARED_KEY_AUTHENTICATION1;
+-#endif
+
+ typedef struct IKEEXT_CERTIFICATE_AUTHENTICATION0_ {
+     IKEEXT_CERT_CONFIG_TYPE inboundConfigType;
diff --git a/src/libcharon/plugins/led/Makefile.am b/src/libcharon/plugins/led/Makefile.am
index fbe779d..18d6af3 100644
--- a/src/libcharon/plugins/led/Makefile.am
+++ b/src/libcharon/plugins/led/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-led.la
diff --git a/src/libcharon/plugins/led/Makefile.in b/src/libcharon/plugins/led/Makefile.in
index f7179cf..78ec666 100644
--- a/src/libcharon/plugins/led/Makefile.in
+++ b/src/libcharon/plugins/led/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-led.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-led.la
diff --git a/src/libcharon/plugins/load_tester/Makefile.am b/src/libcharon/plugins/load_tester/Makefile.am
index e7c0878..31e1b5c 100644
--- a/src/libcharon/plugins/load_tester/Makefile.am
+++ b/src/libcharon/plugins/load_tester/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-load-tester.la
diff --git a/src/libcharon/plugins/load_tester/Makefile.in b/src/libcharon/plugins/load_tester/Makefile.in
index 561d69a..df75c0f 100644
--- a/src/libcharon/plugins/load_tester/Makefile.in
+++ b/src/libcharon/plugins/load_tester/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -276,6 +276,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -294,6 +295,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -321,6 +323,7 @@ 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@
@@ -412,6 +415,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -429,7 +433,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-load-tester.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-load-tester.la
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index e133190..bc7c0ff 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -150,7 +150,7 @@ struct private_load_tester_config_t {
 	/**
 	 * incremental numbering of generated configs
 	 */
-	u_int num;
+	refcount_t num;
 
 	/**
 	 * Dynamic source port, if used
@@ -802,7 +802,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
 {
 	if (streq(name, "load-test"))
 	{
-		return generate_config(this, this->num++);
+		return generate_config(this, (u_int)ref_get(&this->num));
 	}
 	return NULL;
 }
diff --git a/src/libcharon/plugins/load_tester/load_tester_creds.c b/src/libcharon/plugins/load_tester/load_tester_creds.c
index f17d41f..d62c729 100644
--- a/src/libcharon/plugins/load_tester/load_tester_creds.c
+++ b/src/libcharon/plugins/load_tester/load_tester_creds.c
@@ -68,6 +68,11 @@ struct private_load_tester_creds_t {
 	 * Password for EAP
 	 */
 	shared_key_t *pwd;
+
+	/**
+	 * List of certificate distribution points to include in generated certs
+	 */
+	linked_list_t *cdps;
 };
 
 /**
@@ -377,6 +382,7 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
 									BUILD_NOT_BEFORE_TIME, now - 60 * 60 * 24,
 									BUILD_NOT_AFTER_TIME, now + 60 * 60 * 24,
 									BUILD_SERIAL, chunk_from_thing(serial),
+									BUILD_CRL_DISTRIBUTION_POINTS, this->cdps,
 									BUILD_END);
 		peer_key->destroy(peer_key);
 		sans->destroy(sans);
@@ -436,13 +442,14 @@ METHOD(load_tester_creds_t, destroy, void,
 	DESTROY_IF(this->ca);
 	this->psk->destroy(this->psk);
 	this->pwd->destroy(this->pwd);
+	this->cdps->destroy_function(this->cdps, free);
 	free(this);
 }
 
 load_tester_creds_t *load_tester_creds_create()
 {
 	private_load_tester_creds_t *this;
-	char *pwd, *psk, *digest;
+	char *pwd, *psk, *digest, *crl;
 
 	psk = lib->settings->get_str(lib->settings,
 				"%s.plugins.load-tester.preshared_key", default_psk, lib->ns);
@@ -450,6 +457,8 @@ load_tester_creds_t *load_tester_creds_create()
 				"%s.plugins.load-tester.eap_password", default_pwd, lib->ns);
 	digest = lib->settings->get_str(lib->settings,
 				"%s.plugins.load-tester.digest", "sha1", lib->ns);
+	crl = lib->settings->get_str(lib->settings,
+				"%s.plugins.load-tester.crl", NULL, lib->ns);
 
 	INIT(this,
 		.public = {
@@ -465,7 +474,7 @@ load_tester_creds_t *load_tester_creds_create()
 		.private = load_issuer_key(),
 		.ca = load_issuer_cert(),
 		.cas = linked_list_create(),
-		.digest = enum_from_name(hash_algorithm_short_names, digest),
+		.cdps = linked_list_create(),
 		.psk = shared_key_create(SHARED_IKE,
 								 chunk_clone(chunk_create(psk, strlen(psk)))),
 		.pwd = shared_key_create(SHARED_EAP,
@@ -477,14 +486,23 @@ load_tester_creds_t *load_tester_creds_create()
 		this->cas->insert_last(this->cas, this->ca->get_ref(this->ca));
 	}
 
-	if (this->digest == -1)
+	if (!enum_from_name(hash_algorithm_short_names, digest, &this->digest))
 	{
 		DBG1(DBG_CFG, "invalid load-tester digest: '%s', using sha1", digest);
 		this->digest = HASH_SHA1;
 	}
 
+	if (crl)
+	{
+		x509_cdp_t *cdp;
+
+		INIT(cdp,
+			.uri = crl,
+		);
+		this->cdps->insert_last(this->cdps, cdp);
+	}
+
 	load_ca_certs(this);
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/load_tester/load_tester_ipsec.c b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
index 02b1d42..3f256dd 100644
--- a/src/libcharon/plugins/load_tester/load_tester_ipsec.c
+++ b/src/libcharon/plugins/load_tester/load_tester_ipsec.c
@@ -31,14 +31,14 @@ struct private_load_tester_ipsec_t {
 	/**
 	 * faked SPI counter
 	 */
-	u_int32_t spi;
+	refcount_t spi;
 };
 
 METHOD(kernel_ipsec_t, get_spi, status_t,
 	private_load_tester_ipsec_t *this, host_t *src, host_t *dst,
 	u_int8_t protocol, u_int32_t reqid, u_int32_t *spi)
 {
-	*spi = ++this->spi;
+	*spi = (uint32_t)ref_get(&this->spi);
 	return SUCCESS;
 }
 
@@ -53,8 +53,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 	private_load_tester_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, bool initiator, bool encap, bool esn, bool inbound,
+	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,
 	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
 	return SUCCESS;
diff --git a/src/libcharon/plugins/lookip/Makefile.am b/src/libcharon/plugins/lookip/Makefile.am
index 6d71c8c..223654e 100644
--- a/src/libcharon/plugins/lookip/Makefile.am
+++ b/src/libcharon/plugins/lookip/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-lookip.la
diff --git a/src/libcharon/plugins/lookip/Makefile.in b/src/libcharon/plugins/lookip/Makefile.in
index 57aaeea..deb517e 100644
--- a/src/libcharon/plugins/lookip/Makefile.in
+++ b/src/libcharon/plugins/lookip/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -272,6 +272,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -290,6 +291,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -317,6 +319,7 @@ 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@
@@ -408,6 +411,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -425,7 +429,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-lookip.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-lookip.la
diff --git a/src/libcharon/plugins/maemo/Makefile.am b/src/libcharon/plugins/maemo/Makefile.am
index c3c55ba..fe5c963 100644
--- a/src/libcharon/plugins/maemo/Makefile.am
+++ b/src/libcharon/plugins/maemo/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${maemo_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-maemo.la
diff --git a/src/libcharon/plugins/maemo/Makefile.in b/src/libcharon/plugins/maemo/Makefile.in
index e1d4ee3..aa3ade0 100644
--- a/src/libcharon/plugins/maemo/Makefile.in
+++ b/src/libcharon/plugins/maemo/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${maemo_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-maemo.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-maemo.la
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index f0f3105..2e96f8f 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -327,6 +327,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
 							 charon->socket->get_port(charon->socket, FALSE),
 							 hostname, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
 	ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+	ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 
 	peer_cfg = peer_cfg_create(this->current, ike_cfg,
 							   CERT_SEND_IF_ASKED,
@@ -351,6 +352,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
 								 TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE,
 								 ACTION_NONE, FALSE, 0, 0, NULL, NULL, 0);
 	child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+	child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
 	ts = traffic_selector_create_dynamic(0, 0, 65535);
 	child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
 	ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
diff --git a/src/libcharon/plugins/medcli/Makefile.am b/src/libcharon/plugins/medcli/Makefile.am
index f645be2..cfa8259 100644
--- a/src/libcharon/plugins/medcli/Makefile.am
+++ b/src/libcharon/plugins/medcli/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-medcli.la
diff --git a/src/libcharon/plugins/medcli/Makefile.in b/src/libcharon/plugins/medcli/Makefile.in
index b6a04df..919b936 100644
--- a/src/libcharon/plugins/medcli/Makefile.in
+++ b/src/libcharon/plugins/medcli/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-medcli.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-medcli.la
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index d048b00..1fb57b9 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -106,6 +106,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
 							 charon->socket->get_port(charon->socket, FALSE),
 							 address, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0);
 	ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+	ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 	med_cfg = peer_cfg_create(
 		"mediation", ike_cfg,
 		CERT_NEVER_SEND, UNIQUE_REPLACE,
@@ -168,6 +169,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
 								 ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
 								 0, 0, NULL, NULL, 0);
 	child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+	child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
 	child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
 	child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
 	peer_cfg->add_child_cfg(peer_cfg, child_cfg);
@@ -242,6 +244,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool,
 								 ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
 								 0, 0, NULL, NULL, 0);
 	child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+	child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
 	child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
 	child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
 	this->current->add_child_cfg(this->current, child_cfg);
@@ -382,6 +385,7 @@ medcli_config_t *medcli_config_create(database_t *db)
 							  FRAGMENTATION_NO, 0),
 	);
 	this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
+	this->ike->add_proposal(this->ike, proposal_create_default_aead(PROTO_IKE));
 
 	schedule_autoinit(this);
 
diff --git a/src/libcharon/plugins/medsrv/Makefile.am b/src/libcharon/plugins/medsrv/Makefile.am
index ec305da..f212202 100644
--- a/src/libcharon/plugins/medsrv/Makefile.am
+++ b/src/libcharon/plugins/medsrv/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-medsrv.la
diff --git a/src/libcharon/plugins/medsrv/Makefile.in b/src/libcharon/plugins/medsrv/Makefile.in
index 82d985e..ce81fb1 100644
--- a/src/libcharon/plugins/medsrv/Makefile.in
+++ b/src/libcharon/plugins/medsrv/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-medsrv.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-medsrv.la
diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c
index ac6076a..02d805e 100644
--- a/src/libcharon/plugins/medsrv/medsrv_config.c
+++ b/src/libcharon/plugins/medsrv/medsrv_config.c
@@ -145,6 +145,7 @@ medsrv_config_t *medsrv_config_create(database_t *db)
 							  FRAGMENTATION_NO, 0),
 	);
 	this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
+	this->ike->add_proposal(this->ike, proposal_create_default_aead(PROTO_IKE));
 
 	return &this->public;
 }
diff --git a/src/libcharon/plugins/osx_attr/Makefile.am b/src/libcharon/plugins/osx_attr/Makefile.am
index f1ff22e..aa1d462 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.am
+++ b/src/libcharon/plugins/osx_attr/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-osx-attr.la
diff --git a/src/libcharon/plugins/osx_attr/Makefile.in b/src/libcharon/plugins/osx_attr/Makefile.in
index ce8d67c..870b427 100644
--- a/src/libcharon/plugins/osx_attr/Makefile.in
+++ b/src/libcharon/plugins/osx_attr/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-osx-attr.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-osx-attr.la
diff --git a/src/libcharon/plugins/radattr/Makefile.am b/src/libcharon/plugins/radattr/Makefile.am
index a0b0584..15d5a0a 100644
--- a/src/libcharon/plugins/radattr/Makefile.am
+++ b/src/libcharon/plugins/radattr/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libradius
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-radattr.la
diff --git a/src/libcharon/plugins/radattr/Makefile.in b/src/libcharon/plugins/radattr/Makefile.in
index 3dbebd8..35ebf99 100644
--- a/src/libcharon/plugins/radattr/Makefile.in
+++ b/src/libcharon/plugins/radattr/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -420,7 +424,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libradius
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-radattr.la
 @MONOLITHIC_FALSE at libstrongswan_radattr_la_LIBADD = $(top_builddir)/src/libradius/libradius.la
diff --git a/src/libcharon/plugins/radattr/radattr_listener.c b/src/libcharon/plugins/radattr/radattr_listener.c
index aca83aa..1d30460 100644
--- a/src/libcharon/plugins/radattr/radattr_listener.c
+++ b/src/libcharon/plugins/radattr/radattr_listener.c
@@ -68,7 +68,7 @@ static void print_radius_attributes(private_radattr_listener_t *this,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY)
+		if (payload->get_type(payload) == PLV2_NOTIFY)
 		{
 			notify = (notify_payload_t*)payload;
 			if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE)
@@ -144,7 +144,7 @@ METHOD(listener_t, message, bool,
 {
 	if (plain && ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) &&
 		message->get_exchange_type(message) == IKE_AUTH &&
-		message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
+		message->get_payload(message, PLV2_EAP))
 	{
 		if (incoming)
 		{
diff --git a/src/libcharon/plugins/smp/Makefile.am b/src/libcharon/plugins/smp/Makefile.am
index 67b4b2a..3aa533e 100644
--- a/src/libcharon/plugins/smp/Makefile.am
+++ b/src/libcharon/plugins/smp/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-smp.la
diff --git a/src/libcharon/plugins/smp/Makefile.in b/src/libcharon/plugins/smp/Makefile.in
index e0134e7..35e7f2a 100644
--- a/src/libcharon/plugins/smp/Makefile.in
+++ b/src/libcharon/plugins/smp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-smp.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-smp.la
diff --git a/src/libcharon/plugins/socket_default/Makefile.am b/src/libcharon/plugins/socket_default/Makefile.am
index d734b31..e524ffd 100644
--- a/src/libcharon/plugins/socket_default/Makefile.am
+++ b/src/libcharon/plugins/socket_default/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-socket-default.la
diff --git a/src/libcharon/plugins/socket_default/Makefile.in b/src/libcharon/plugins/socket_default/Makefile.in
index 894c1f9..bee1259 100644
--- a/src/libcharon/plugins/socket_default/Makefile.in
+++ b/src/libcharon/plugins/socket_default/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-socket-default.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-socket-default.la
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.am b/src/libcharon/plugins/socket_dynamic/Makefile.am
index 04973e5..a1e21b9 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.am
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-socket-dynamic.la
diff --git a/src/libcharon/plugins/socket_dynamic/Makefile.in b/src/libcharon/plugins/socket_dynamic/Makefile.in
index a0e2d2d..073806d 100644
--- a/src/libcharon/plugins/socket_dynamic/Makefile.in
+++ b/src/libcharon/plugins/socket_dynamic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -419,7 +423,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-socket-dynamic.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-socket-dynamic.la
diff --git a/src/libcharon/plugins/socket_win/Makefile.am b/src/libcharon/plugins/socket_win/Makefile.am
new file mode 100644
index 0000000..f01178f
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/Makefile.am
@@ -0,0 +1,21 @@
+AM_CPPFLAGS = \
+	-I${linux_headers} \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-socket-win.la
+else
+plugin_LTLIBRARIES = libstrongswan-socket-win.la
+endif
+
+libstrongswan_socket_win_la_SOURCES = \
+	socket_win_socket.h socket_win_socket.c \
+	socket_win_plugin.h socket_win_plugin.c
+
+libstrongswan_socket_win_la_LDFLAGS = -module -avoid-version
+libstrongswan_socket_win_la_LIBADD  = -lws2_32
diff --git a/src/libcharon/plugins/socket_win/Makefile.in b/src/libcharon/plugins/socket_win/Makefile.in
new file mode 100644
index 0000000..ff38e81
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/Makefile.in
@@ -0,0 +1,769 @@
+# 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/socket_win
+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_socket_win_la_DEPENDENCIES =
+am_libstrongswan_socket_win_la_OBJECTS = socket_win_socket.lo \
+	socket_win_plugin.lo
+libstrongswan_socket_win_la_OBJECTS =  \
+	$(am_libstrongswan_socket_win_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_socket_win_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_socket_win_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_socket_win_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_socket_win_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_socket_win_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_socket_win_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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 \
+	-I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-socket-win.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-socket-win.la
+libstrongswan_socket_win_la_SOURCES = \
+	socket_win_socket.h socket_win_socket.c \
+	socket_win_plugin.h socket_win_plugin.c
+
+libstrongswan_socket_win_la_LDFLAGS = -module -avoid-version
+libstrongswan_socket_win_la_LIBADD = -lws2_32
+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/socket_win/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/socket_win/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-socket-win.la: $(libstrongswan_socket_win_la_OBJECTS) $(libstrongswan_socket_win_la_DEPENDENCIES) $(EXTRA_libstrongswan_socket_win_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_socket_win_la_LINK) $(am_libstrongswan_socket_win_la_rpath) $(libstrongswan_socket_win_la_OBJECTS) $(libstrongswan_socket_win_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/socket_win_plugin.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/socket_win_socket.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/socket_win/socket_win_plugin.c b/src/libcharon/plugins/socket_win/socket_win_plugin.c
new file mode 100644
index 0000000..a0ef085
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_plugin.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 "socket_win_plugin.h"
+#include "socket_win_socket.h"
+
+#include <daemon.h>
+
+typedef struct private_socket_win_plugin_t private_socket_win_plugin_t;
+
+/**
+ * Private data of socket plugin
+ */
+struct private_socket_win_plugin_t {
+
+	/**
+	 * Implements plugin interface
+	 */
+	socket_win_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_socket_win_plugin_t *this)
+{
+	return "socket-win";
+}
+
+METHOD(plugin_t, destroy, void,
+	private_socket_win_plugin_t *this)
+{
+	free(this);
+}
+
+METHOD(plugin_t, get_features, int,
+	private_socket_win_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK(socket_register, socket_win_socket_create),
+			PLUGIN_PROVIDE(CUSTOM, "socket"),
+				PLUGIN_DEPENDS(CUSTOM, "kernel-ipsec"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+/**
+ * Create instance of socket-win plugin
+ */
+plugin_t *socket_win_plugin_create()
+{
+	private_socket_win_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/socket_win/socket_win_plugin.h b/src/libcharon/plugins/socket_win/socket_win_plugin.h
new file mode 100644
index 0000000..c4873ce
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup socket_win socket_win
+ * @ingroup cplugins
+ *
+ * @defgroup socket_win_plugin socket_win_plugin
+ * @{ @ingroup socket_win
+ */
+
+#ifndef SOCKET_WIN_PLUGIN_H_
+#define SOCKET_WIN_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct socket_win_plugin_t socket_win_plugin_t;
+
+/**
+ * Winsock2 based socket implementation plugin.
+ */
+struct socket_win_plugin_t {
+
+	/**
+	 * implements plugin interface
+	 */
+	plugin_t plugin;
+};
+
+#endif /** SOCKET_WIN_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.c b/src/libcharon/plugins/socket_win/socket_win_socket.c
new file mode 100644
index 0000000..5ebe04a
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_socket.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/* for WSAID_WSASENDMSG, Windows 7 */
+#define _WIN32_WINNT 0x0601
+
+#include "socket_win_socket.h"
+
+#include <library.h>
+#include <hydra.h>
+#include <threading/thread.h>
+#include <daemon.h>
+
+#include <mswsock.h>
+
+/* Maximum size of a packet */
+#define MAX_PACKET 10000
+
+/* number of sockets in use */
+#define SOCKET_COUNT 2
+
+/* missing on MinGW */
+#ifndef IPV6_V6ONLY
+# define IPV6_V6ONLY 27
+#endif
+
+/* GUIDS to lookup WSASend/RecvMsg */
+static GUID WSARecvMsgGUID = WSAID_WSARECVMSG;
+static GUID WSASendMsgGUID = WSAID_WSASENDMSG;
+
+typedef struct private_socket_win_socket_t private_socket_win_socket_t;
+
+/**
+ * Private data of an socket_t object
+ */
+struct private_socket_win_socket_t {
+
+	/**
+	 * public functions
+	 */
+	socket_win_socket_t public;
+
+	/**
+	 * Port for each socket
+	 */
+	u_int16_t ports[SOCKET_COUNT];
+
+	/**
+	 * IPv4/IPv6 dual-use sockets
+	 */
+	SOCKET socks[SOCKET_COUNT];
+
+	/**
+	 * Events to wait for socket data
+	 */
+	HANDLE events[SOCKET_COUNT];
+
+	/**
+	 * Maximum packet size to receive
+	 */
+	int max_packet;
+
+	/**
+	 * WSASendMsg function
+	 */
+	int WINAPI (*WSASendMsg)(SOCKET, LPWSAMSG, DWORD, LPDWORD,
+					LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
+
+	/**
+	 * WSARecvMsg function
+	 */
+	int WINAPI (*WSARecvMsg)(SOCKET, LPWSAMSG, LPDWORD,
+					LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
+};
+
+METHOD(socket_t, receiver, status_t,
+	private_socket_win_socket_t *this, packet_t **out)
+{
+	char buf[this->max_packet], cbuf[128];
+	bool old;
+	DWORD i, len, err;
+	WSAMSG msg;
+	WSABUF data;
+	WSACMSGHDR *cmsg;
+	SOCKADDR_IN6 addr;
+	host_t *src = NULL, *dst = NULL;
+	packet_t *pkt;
+
+	data.buf = buf;
+	data.len = sizeof(buf);
+
+	memset(&msg, 0, sizeof(msg));
+	msg.name = (struct sockaddr*)&addr;
+	msg.namelen = sizeof(addr);
+	msg.lpBuffers = &data;
+	msg.dwBufferCount = 1;
+	msg.Control.buf = cbuf;
+	msg.Control.len = sizeof(cbuf);
+
+	/* wait for socket events */
+	old = thread_cancelability(TRUE);
+	i = WSAWaitForMultipleEvents(SOCKET_COUNT, this->events,
+								 FALSE, INFINITE, TRUE);
+	thread_cancelability(old);
+	if (i < WSA_WAIT_EVENT_0 || i >= WSA_WAIT_EVENT_0 + SOCKET_COUNT)
+	{
+		DBG1(DBG_NET, "waiting on sockets failed: %d", WSAGetLastError());
+		return FAILED;
+	}
+	i -= WSA_WAIT_EVENT_0;
+
+	/* WSAEvents must be reset manually */
+	WSAResetEvent(this->events[i]);
+
+	if (this->WSARecvMsg(this->socks[i], &msg, &len,
+						 NULL, NULL) == SOCKET_ERROR)
+	{
+		err = WSAGetLastError();
+		/* ignore WSAECONNRESET; this is returned for any ICMP port unreachable,
+		 * for a packet we sent, but is most likely not related to the packet
+		 * we try to receive. */
+		if (err != WSAECONNRESET)
+		{
+			DBG1(DBG_NET, "reading from socket failed: %d", WSAGetLastError());
+		}
+		return FAILED;
+	}
+
+	DBG3(DBG_NET, "received packet %b", buf, (int)len);
+
+	for (cmsg = WSA_CMSG_FIRSTHDR(&msg); dst == NULL && cmsg != NULL;
+		 cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
+	{
+		if (cmsg->cmsg_level == IPPROTO_IP &&
+			cmsg->cmsg_type == IP_PKTINFO)
+		{
+			struct in_pktinfo *pktinfo;
+			struct sockaddr_in sin = {
+				.sin_family = AF_INET,
+			};
+
+			pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
+			sin.sin_addr = pktinfo->ipi_addr;
+			sin.sin_port = htons(this->ports[i]);
+			dst = host_create_from_sockaddr((struct sockaddr*)&sin);
+		}
+		if (cmsg->cmsg_level == IPPROTO_IPV6 &&
+			cmsg->cmsg_type == IPV6_PKTINFO)
+		{
+			struct in6_pktinfo *pktinfo;
+			struct sockaddr_in6 sin = {
+				.sin6_family = AF_INET6,
+			};
+
+			pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
+			sin.sin6_addr = pktinfo->ipi6_addr;
+			sin.sin6_port = htons(this->ports[i]);
+			dst = host_create_from_sockaddr((struct sockaddr*)&sin);
+		}
+	}
+
+	if (!dst)
+	{
+		DBG1(DBG_NET, "receiving IP destination address failed");
+		return FAILED;
+	}
+
+	switch (dst->get_family(dst))
+	{
+		case AF_INET6:
+			src = host_create_from_sockaddr((struct sockaddr*)&addr);
+			break;
+		case AF_INET:
+			/* extract v4 address from mapped v6 */
+			src = host_create_from_chunk(AF_INET,
+								chunk_create(addr.sin6_addr.u.Byte + 12, 4),
+								ntohs(addr.sin6_port));
+			break;
+	}
+	if (!src)
+	{
+		DBG1(DBG_NET, "receiving IP source address failed");
+		dst->destroy(dst);
+		return FAILED;
+	}
+
+	pkt = packet_create();
+	pkt->set_source(pkt, src);
+	pkt->set_destination(pkt, dst);
+	DBG2(DBG_NET, "received packet: from %#H to %#H", src, dst);
+	pkt->set_data(pkt, chunk_clone(chunk_create(buf, len)));
+
+	*out = pkt;
+	return SUCCESS;
+}
+
+METHOD(socket_t, sender, status_t,
+	private_socket_win_socket_t *this, packet_t *packet)
+{
+	u_int16_t port;
+	int i = -1, j;
+	host_t *src, *dst;
+	WSAMSG msg;
+	DWORD len;
+	WSABUF data;
+	WSACMSGHDR *cmsg;
+	SOCKADDR_IN6 addr = {
+		.sin6_family = AF_INET6,
+		.sin6_addr = {
+			.u = {
+				.Byte = {
+					/* v6-mapped-v4 by default */
+					0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+					0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,
+				},
+			},
+		},
+	};
+	char buf[WSA_CMSG_SPACE(max(sizeof(struct in6_pktinfo),
+								sizeof(struct in_pktinfo)))];
+
+	src = packet->get_source(packet);
+	dst = packet->get_destination(packet);
+	data.len = packet->get_data(packet).len;
+	data.buf = packet->get_data(packet).ptr;
+
+	DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
+
+	DBG3(DBG_NET, "sending packet %b", data.buf, (int)data.len);
+
+	port = src->get_port(src);
+	for (j = 0; j < SOCKET_COUNT; j++)
+	{
+		if (!port || this->ports[j] == port)
+		{
+			i = j;
+			break;
+		}
+	}
+	if (i == -1)
+	{
+		DBG1(DBG_NET, "no socket found to send packet from port %u", port);
+		return FAILED;
+	}
+
+	/* copy destination IPv6, or last 32 bits of mapped IPv4 address */
+	len = dst->get_address(dst).len;
+	if (len > sizeof(addr.sin6_addr))
+	{
+		return FAILED;
+	}
+	memcpy(addr.sin6_addr.u.Byte + sizeof(addr.sin6_addr) - len,
+		   dst->get_address(dst).ptr, len);
+	addr.sin6_port = htons(dst->get_port(dst));
+
+	memset(&msg, 0, sizeof(msg));
+	msg.name = (struct sockaddr*)&addr;
+	msg.namelen = sizeof(addr);
+	msg.lpBuffers = &data;
+	msg.dwBufferCount = 1;
+
+	if (!src->is_anyaddr(src))
+	{
+		memset(buf, 0, sizeof(buf));
+		msg.Control.buf = buf;
+
+		switch (src->get_family(src))
+		{
+			case AF_INET:
+			{
+				struct in_pktinfo *pktinfo;
+				SOCKADDR_IN *sin;
+
+				msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
+				cmsg = WSA_CMSG_FIRSTHDR(&msg);
+				cmsg->cmsg_level = IPPROTO_IP;
+				cmsg->cmsg_type = IP_PKTINFO;
+				cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
+				pktinfo = (struct in_pktinfo*)WSA_CMSG_DATA(cmsg);
+				sin = (SOCKADDR_IN*)src->get_sockaddr(src);
+				pktinfo->ipi_addr = sin->sin_addr;
+				break;
+			}
+			case AF_INET6:
+			{
+				struct in6_pktinfo *pktinfo;
+				SOCKADDR_IN6 *sin;
+
+				msg.Control.len = WSA_CMSG_SPACE(sizeof(*pktinfo));
+				cmsg = WSA_CMSG_FIRSTHDR(&msg);
+				cmsg->cmsg_level = IPPROTO_IPV6;
+				cmsg->cmsg_type = IPV6_PKTINFO;
+				cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
+				pktinfo = (struct in6_pktinfo*)WSA_CMSG_DATA(cmsg);
+				sin = (SOCKADDR_IN6*)src->get_sockaddr(src);
+				pktinfo->ipi6_addr = sin->sin6_addr;
+				break;
+			}
+		}
+	}
+
+	if (this->WSASendMsg(this->socks[i], &msg, 0, &len,
+						 NULL, NULL) == SOCKET_ERROR)
+	{
+		DBG1(DBG_NET, "sending packet failed: %d", WSAGetLastError());
+		return FAILED;
+	}
+	return SUCCESS;
+}
+
+METHOD(socket_t, get_port, u_int16_t,
+	private_socket_win_socket_t *this, bool nat)
+{
+	return this->ports[nat != 0];
+}
+
+METHOD(socket_t, supported_families, socket_family_t,
+	private_socket_win_socket_t *this)
+{
+	return SOCKET_FAMILY_IPV4 | SOCKET_FAMILY_IPV6;
+}
+
+/**
+ * Open an IPv4/IPv6 dual-use socket to send and receive packets
+ */
+static SOCKET open_socket(private_socket_win_socket_t *this, int i)
+{
+	SOCKADDR_IN6 addr = {
+		.sin6_family = AF_INET6,
+		.sin6_port = htons(this->ports[i]),
+	};
+	int addrlen = sizeof(addr);
+	BOOL on = TRUE, off = FALSE;
+	DWORD dwon = TRUE;
+	SOCKET s;
+
+	s = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
+	if (s == INVALID_SOCKET)
+	{
+		DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
+		return INVALID_SOCKET;
+	}
+	/* enable IPv4 on IPv6 socket */
+	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+				   (const char*)&off, sizeof(off)) == SOCKET_ERROR)
+	{
+		DBG1(DBG_NET, "using dual-mode socket failed: %d", WSAGetLastError());
+		closesocket(s);
+		return INVALID_SOCKET;
+	}
+	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+				   (const char*)&on, sizeof(on)) == SOCKET_ERROR)
+	{
+		DBG1(DBG_NET, "enabling SO_REUSEADDR failed: %d", WSAGetLastError());
+		closesocket(s);
+		return INVALID_SOCKET;
+	}
+	if (bind(s, (const struct sockaddr*)&addr, addrlen) == SOCKET_ERROR)
+	{
+		DBG1(DBG_NET, "unable to bind socket: %d", WSAGetLastError());
+		closesocket(s);
+		return INVALID_SOCKET;
+	}
+	/* retrieve randomly allocated port if needed */
+	if (this->ports[i] == 0)
+	{
+		if (getsockname(s, (struct sockaddr*)&addr,
+						&addrlen) == SOCKET_ERROR)
+		{
+			DBG1(DBG_NET, "unable to determine port: %d", WSAGetLastError());
+			closesocket(s);
+			return INVALID_SOCKET;
+		}
+		this->ports[i] = ntohs(addr.sin6_port);
+	}
+	/* PKTINFO is required for both protocol families */
+	if (setsockopt(s, IPPROTO_IP, IP_PKTINFO,
+				   (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
+	{
+		DBG1(DBG_NET, "unable to set IP_PKTINFO: %d", WSAGetLastError());
+		closesocket(s);
+		return INVALID_SOCKET;
+	}
+	if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
+				   (char*)&dwon, sizeof(dwon)) == SOCKET_ERROR)
+	{
+		DBG1(DBG_NET, "unable to set IP6_PKTINFO: %d", WSAGetLastError());
+		closesocket(s);
+		return INVALID_SOCKET;
+	}
+	if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
+												s, AF_INET))
+	{
+		DBG1(DBG_NET, "installing IPv4 IKE bypass policy failed");
+	}
+	if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
+												s, AF_INET6))
+	{
+		DBG1(DBG_NET, "installing IPv6 IKE bypass policy failed");
+	}
+	return s;
+}
+
+METHOD(socket_t, destroy, void,
+	private_socket_win_socket_t *this)
+{
+	int i;
+
+	for (i = 0; i < SOCKET_COUNT; i++)
+	{
+		if (this->socks[i] != INVALID_SOCKET)
+		{
+			closesocket(this->socks[i]);
+		}
+		if (this->events[i] != WSA_INVALID_EVENT)
+		{
+			WSACloseEvent(this->events[i]);
+		}
+	}
+	free(this);
+}
+
+/*
+ * See header for description
+ */
+socket_win_socket_t *socket_win_socket_create()
+{
+	private_socket_win_socket_t *this;
+	DWORD len;
+	int i;
+
+	INIT(this,
+		.public = {
+			.socket = {
+				.send = _sender,
+				.receive = _receiver,
+				.get_port = _get_port,
+				.supported_families = _supported_families,
+				.destroy = _destroy,
+			},
+		},
+		.ports = {
+			lib->settings->get_int(lib->settings,
+							"%s.port", CHARON_UDP_PORT, lib->ns),
+			lib->settings->get_int(lib->settings,
+							"%s.port_nat_t", CHARON_NATT_PORT, lib->ns),
+		},
+		.max_packet = lib->settings->get_int(lib->settings,
+							"%s.max_packet", MAX_PACKET, lib->ns),
+	);
+
+	for (i = 0; i < SOCKET_COUNT; i++)
+	{
+		this->socks[i] = open_socket(this, i);
+		this->events[i] = WSACreateEvent();
+	}
+
+	for (i = 0; i < SOCKET_COUNT; i++)
+	{
+		if (this->events[i] == WSA_INVALID_EVENT ||
+			this->socks[i] == INVALID_SOCKET)
+		{
+			DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError());
+			destroy(this);
+			return NULL;
+		}
+		if (WSAEventSelect(this->socks[i], this->events[i],
+						   FD_READ) == SOCKET_ERROR)
+		{
+			DBG1(DBG_NET, "WSAEventSelect() failed: %d", WSAGetLastError());
+			destroy(this);
+			return NULL;
+		}
+	}
+
+	if (WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
+			&WSASendMsgGUID, sizeof(WSASendMsgGUID), &this->WSASendMsg,
+			sizeof(this->WSASendMsg), &len, NULL, NULL) != 0 ||
+		WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER,
+			&WSARecvMsgGUID, sizeof(WSARecvMsgGUID), &this->WSARecvMsg,
+			sizeof(this->WSARecvMsg), &len, NULL, NULL) != 0)
+	{
+		DBG1(DBG_NET, "send/recvmsg() lookup failed: %d", WSAGetLastError());
+		destroy(this);
+		return NULL;
+	}
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.h b/src/libcharon/plugins/socket_win/socket_win_socket.h
new file mode 100644
index 0000000..21699c3
--- /dev/null
+++ b/src/libcharon/plugins/socket_win/socket_win_socket.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup socket_win_socket socket_win_socket
+ * @{ @ingroup socket_win
+ */
+
+#ifndef SOCKET_WIN_SOCKET_H_
+#define SOCKET_WIN_SOCKET_H_
+
+typedef struct socket_win_socket_t socket_win_socket_t;
+
+#include <network/socket.h>
+
+/**
+ * Winsock2 based socket implementation.
+ */
+struct socket_win_socket_t {
+
+	/**
+	 * Implements the socket_t interface.
+	 */
+	socket_t socket;
+};
+
+/**
+ * Create a socket_win_socket instance.
+ */
+socket_win_socket_t *socket_win_socket_create();
+
+#endif /** SOCKET_WIN_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/sql/Makefile.am b/src/libcharon/plugins/sql/Makefile.am
index fd56931..c947db8 100644
--- a/src/libcharon/plugins/sql/Makefile.am
+++ b/src/libcharon/plugins/sql/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-sql.la
diff --git a/src/libcharon/plugins/sql/Makefile.in b/src/libcharon/plugins/sql/Makefile.in
index 02967d0..208b900 100644
--- a/src/libcharon/plugins/sql/Makefile.in
+++ b/src/libcharon/plugins/sql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-sql.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-sql.la
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index a8d34f2..c47c7c0 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -153,6 +153,7 @@ static void add_esp_proposals(private_sql_config_t *this,
 	if (use_default)
 	{
 		child->add_proposal(child, proposal_create_default(PROTO_ESP));
+		child->add_proposal(child, proposal_create_default_aead(PROTO_ESP));
 	}
 }
 
@@ -242,6 +243,7 @@ static void add_ike_proposals(private_sql_config_t *this,
 	if (use_default)
 	{
 		ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+		ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
 	}
 }
 
diff --git a/src/libcharon/plugins/stroke/Makefile.am b/src/libcharon/plugins/stroke/Makefile.am
index 9509b1b..b906887 100644
--- a/src/libcharon/plugins/stroke/Makefile.am
+++ b/src/libcharon/plugins/stroke/Makefile.am
@@ -7,7 +7,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-stroke.la
diff --git a/src/libcharon/plugins/stroke/Makefile.in b/src/libcharon/plugins/stroke/Makefile.in
index 253203d..59a5983 100644
--- a/src/libcharon/plugins/stroke/Makefile.in
+++ b/src/libcharon/plugins/stroke/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -423,7 +427,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-stroke.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-stroke.la
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index e5e6d92..62967b0 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -174,10 +174,12 @@ static void add_proposals(private_stroke_config_t *this, char *string,
 	if (ike_cfg)
 	{
 		ike_cfg->add_proposal(ike_cfg, proposal_create_default(proto));
+		ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(proto));
 	}
 	else
 	{
 		child_cfg->add_proposal(child_cfg, proposal_create_default(proto));
+		child_cfg->add_proposal(child_cfg, proposal_create_default_aead(proto));
 	}
 }
 
@@ -1149,6 +1151,10 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
 				map_action(msg->add_conn.close_action), msg->add_conn.ipcomp,
 				msg->add_conn.inactivity, msg->add_conn.reqid,
 				&mark_in, &mark_out, msg->add_conn.tfc);
+	if (msg->add_conn.replay_window != -1)
+	{
+		child_cfg->set_replay_window(child_cfg, msg->add_conn.replay_window);
+	}
 	child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
 											msg->add_conn.install_policy);
 	add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 169ff2b..54dd56e 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -107,6 +107,19 @@ struct private_stroke_socket_t {
 };
 
 /**
+ * Helper macro to log configuration options, but only if they are defined.
+ */
+#define DBG_OPT(...) VA_ARGS_DISPATCH(DBG_OPT, __VA_ARGS__)(__VA_ARGS__)
+#define DBG_OPT2(fmt, val) ({ \
+	typeof(val) _val = val; \
+	if (_val) { DBG2(DBG_CFG, fmt, _val); } \
+})
+#define DBG_OPT3(fmt, label, val) ({ \
+	typeof(val) _val = val; \
+	if (_val) { DBG2(DBG_CFG, fmt, label, _val); } \
+})
+
+/**
  * Helper function which corrects the string pointers
  * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
  * contains RELATIVE addresses (relative to the beginning of the
@@ -157,22 +170,22 @@ static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
 	pop_string(msg, &end->cert_policy);
 	pop_string(msg, &end->updown);
 
-	DBG2(DBG_CFG, "  %s=%s", label, end->address);
-	DBG2(DBG_CFG, "  %ssubnet=%s", label, end->subnets);
-	DBG2(DBG_CFG, "  %ssourceip=%s", label, end->sourceip);
-	DBG2(DBG_CFG, "  %sdns=%s", label, end->dns);
-	DBG2(DBG_CFG, "  %sauth=%s", label, end->auth);
-	DBG2(DBG_CFG, "  %sauth2=%s", label, end->auth2);
-	DBG2(DBG_CFG, "  %sid=%s", label, end->id);
-	DBG2(DBG_CFG, "  %sid2=%s", label, end->id2);
-	DBG2(DBG_CFG, "  %srsakey=%s", label, end->rsakey);
-	DBG2(DBG_CFG, "  %scert=%s", label, end->cert);
-	DBG2(DBG_CFG, "  %scert2=%s", label, end->cert2);
-	DBG2(DBG_CFG, "  %sca=%s", label, end->ca);
-	DBG2(DBG_CFG, "  %sca2=%s", label, end->ca2);
-	DBG2(DBG_CFG, "  %sgroups=%s", label, end->groups);
-	DBG2(DBG_CFG, "  %sgroups2=%s", label, end->groups2);
-	DBG2(DBG_CFG, "  %supdown=%s", label, end->updown);
+	DBG_OPT("  %s=%s", label, end->address);
+	DBG_OPT("  %ssubnet=%s", label, end->subnets);
+	DBG_OPT("  %ssourceip=%s", label, end->sourceip);
+	DBG_OPT("  %sdns=%s", label, end->dns);
+	DBG_OPT("  %sauth=%s", label, end->auth);
+	DBG_OPT("  %sauth2=%s", label, end->auth2);
+	DBG_OPT("  %sid=%s", label, end->id);
+	DBG_OPT("  %sid2=%s", label, end->id2);
+	DBG_OPT("  %srsakey=%s", label, end->rsakey);
+	DBG_OPT("  %scert=%s", label, end->cert);
+	DBG_OPT("  %scert2=%s", label, end->cert2);
+	DBG_OPT("  %sca=%s", label, end->ca);
+	DBG_OPT("  %sca2=%s", label, end->ca2);
+	DBG_OPT("  %sgroups=%s", label, end->groups);
+	DBG_OPT("  %sgroups2=%s", label, end->groups2);
+	DBG_OPT("  %supdown=%s", label, end->updown);
 }
 
 /**
@@ -194,20 +207,20 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
 	pop_string(msg, &msg->add_conn.algorithms.ah);
 	pop_string(msg, &msg->add_conn.ikeme.mediated_by);
 	pop_string(msg, &msg->add_conn.ikeme.peerid);
-	DBG2(DBG_CFG, "  eap_identity=%s", msg->add_conn.eap_identity);
-	DBG2(DBG_CFG, "  aaa_identity=%s", msg->add_conn.aaa_identity);
-	DBG2(DBG_CFG, "  xauth_identity=%s", msg->add_conn.xauth_identity);
-	DBG2(DBG_CFG, "  ike=%s", msg->add_conn.algorithms.ike);
-	DBG2(DBG_CFG, "  esp=%s", msg->add_conn.algorithms.esp);
-	DBG2(DBG_CFG, "  ah=%s", msg->add_conn.algorithms.ah);
-	DBG2(DBG_CFG, "  dpddelay=%d", msg->add_conn.dpd.delay);
-	DBG2(DBG_CFG, "  dpdtimeout=%d", msg->add_conn.dpd.timeout);
-	DBG2(DBG_CFG, "  dpdaction=%d", msg->add_conn.dpd.action);
-	DBG2(DBG_CFG, "  closeaction=%d", msg->add_conn.close_action);
-	DBG2(DBG_CFG, "  mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
-	DBG2(DBG_CFG, "  mediated_by=%s", msg->add_conn.ikeme.mediated_by);
-	DBG2(DBG_CFG, "  me_peerid=%s", msg->add_conn.ikeme.peerid);
-	DBG2(DBG_CFG, "  keyexchange=ikev%u", msg->add_conn.version);
+	DBG_OPT("  eap_identity=%s", msg->add_conn.eap_identity);
+	DBG_OPT("  aaa_identity=%s", msg->add_conn.aaa_identity);
+	DBG_OPT("  xauth_identity=%s", msg->add_conn.xauth_identity);
+	DBG_OPT("  ike=%s", msg->add_conn.algorithms.ike);
+	DBG_OPT("  esp=%s", msg->add_conn.algorithms.esp);
+	DBG_OPT("  ah=%s", msg->add_conn.algorithms.ah);
+	DBG_OPT("  dpddelay=%d", msg->add_conn.dpd.delay);
+	DBG_OPT("  dpdtimeout=%d", msg->add_conn.dpd.timeout);
+	DBG_OPT("  dpdaction=%d", msg->add_conn.dpd.action);
+	DBG_OPT("  closeaction=%d", msg->add_conn.close_action);
+	DBG_OPT("  mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
+	DBG_OPT("  mediated_by=%s", msg->add_conn.ikeme.mediated_by);
+	DBG_OPT("  me_peerid=%s", msg->add_conn.ikeme.peerid);
+	DBG_OPT("  keyexchange=ikev%u", msg->add_conn.version);
 
 	this->config->add(this->config, msg);
 	this->attribute->add_dns(this->attribute, msg);
@@ -311,13 +324,13 @@ static void stroke_add_ca(private_stroke_socket_t *this,
 	pop_string(msg, &msg->add_ca.ocspuri);
 	pop_string(msg, &msg->add_ca.ocspuri2);
 	pop_string(msg, &msg->add_ca.certuribase);
-	DBG2(DBG_CFG, "ca %s",            msg->add_ca.name);
-	DBG2(DBG_CFG, "  cacert=%s",      msg->add_ca.cacert);
-	DBG2(DBG_CFG, "  crluri=%s",      msg->add_ca.crluri);
-	DBG2(DBG_CFG, "  crluri2=%s",     msg->add_ca.crluri2);
-	DBG2(DBG_CFG, "  ocspuri=%s",     msg->add_ca.ocspuri);
-	DBG2(DBG_CFG, "  ocspuri2=%s",    msg->add_ca.ocspuri2);
-	DBG2(DBG_CFG, "  certuribase=%s", msg->add_ca.certuribase);
+	DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
+	DBG_OPT("  cacert=%s", msg->add_ca.cacert);
+	DBG_OPT("  crluri=%s", msg->add_ca.crluri);
+	DBG_OPT("  crluri2=%s", msg->add_ca.crluri2);
+	DBG_OPT("  ocspuri=%s", msg->add_ca.ocspuri);
+	DBG_OPT("  ocspuri2=%s", msg->add_ca.ocspuri2);
+	DBG_OPT("  certuribase=%s", msg->add_ca.certuribase);
 
 	this->ca->add(this->ca, msg);
 }
@@ -584,8 +597,7 @@ static void stroke_loglevel(private_stroke_socket_t *this,
 	}
 	else
 	{
-		group = enum_from_name(debug_names, msg->loglevel.type);
-		if ((int)group < 0)
+		if (!enum_from_name(debug_names, msg->loglevel.type, &group))
 		{
 			fprintf(out, "unknown type '%s'!\n", msg->loglevel.type);
 			return;
diff --git a/src/libcharon/plugins/systime_fix/Makefile.in b/src/libcharon/plugins/systime_fix/Makefile.in
index 76b2c57..769ad52 100644
--- a/src/libcharon/plugins/systime_fix/Makefile.in
+++ b/src/libcharon/plugins/systime_fix/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.am b/src/libcharon/plugins/tnc_ifmap/Makefile.am
index dfbb1b6..90fbf46 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.am
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-tnc-ifmap.la
diff --git a/src/libcharon/plugins/tnc_ifmap/Makefile.in b/src/libcharon/plugins/tnc_ifmap/Makefile.in
index 1941130..51d46a6 100644
--- a/src/libcharon/plugins/tnc_ifmap/Makefile.in
+++ b/src/libcharon/plugins/tnc_ifmap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ 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@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -423,7 +427,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnc-ifmap.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-tnc-ifmap.la
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.am b/src/libcharon/plugins/tnc_pdp/Makefile.am
index 48de825..3478c5b 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.am
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.am
@@ -9,7 +9,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libpttls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la
diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.in b/src/libcharon/plugins/tnc_pdp/Makefile.in
index 875aa99..531c00c 100644
--- a/src/libcharon/plugins/tnc_pdp/Makefile.in
+++ b/src/libcharon/plugins/tnc_pdp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -270,6 +270,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -288,6 +289,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -315,6 +317,7 @@ 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@
@@ -406,6 +409,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -427,7 +431,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libpttls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-tnc-pdp.la
diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
index 89237f5..109c216 100644
--- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
+++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c
@@ -18,6 +18,7 @@
 
 #include <errno.h>
 #include <unistd.h>
+#include <time.h>
 
 #include <radius_message.h>
 #include <radius_mppe.h>
@@ -37,7 +38,7 @@
 #include <sa/eap/eap_method.h>
 
 typedef struct private_tnc_pdp_t private_tnc_pdp_t;
-
+typedef struct client_entry_t client_entry_t;
 /**
  * Default RADIUS port, when not configured
  */
@@ -48,6 +49,8 @@ typedef struct private_tnc_pdp_t private_tnc_pdp_t;
  */
 #define MAX_PACKET 4096
 
+#define RADIUS_RETRANSMIT_TIMEOUT	30 /* seconds */
+
 /**
  * private data of tnc_pdp_t
  */
@@ -99,6 +102,11 @@ struct private_tnc_pdp_t {
 	chunk_t secret;
 
 	/**
+	 * RADIUS clients
+	 */
+	linked_list_t *clients;
+
+	/**
 	 * MD5 hasher
 	 */
 	hasher_t *hasher;
@@ -121,6 +129,33 @@ struct private_tnc_pdp_t {
 };
 
 /**
+ * Client entry helping to detect RADIUS packet retransmissions
+ */
+struct client_entry_t {
+
+	/**
+	 * IP host address and port of client
+	 */
+	host_t *host;
+
+	/**
+	 * Time of last RADIUS Access-Request received from client
+	 */
+	time_t last_time;
+
+	/**
+	 * Identifier of last RADIUS Access-Request received from client
+	 */
+	uint8_t last_id;
+};
+
+static void free_client_entry(client_entry_t *this)
+{
+	this->host->destroy(this->host);
+	free(this);
+}
+
+/**
  * Open IPv4 or IPv6 UDP socket
  */
 static int open_udp_socket(int family, u_int16_t port)
@@ -663,16 +698,24 @@ static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even
 {
 	radius_message_t *request;
 	char buffer[MAX_PACKET];
+	client_entry_t *client;
+	bool retransmission = FALSE, found = FALSE, stale;
+	enumerator_t *enumerator;
 	int bytes_read = 0;
 	host_t *source;
+	uint8_t id;
+	time_t now;
+
 	union {
 		struct sockaddr_in in4;
 		struct sockaddr_in6 in6;
 	} src;
+
 	struct iovec iov = {
 		.iov_base = buffer,
 		.iov_len = MAX_PACKET,
 	};
+
 	struct msghdr msg = {
 		.msg_name = &src,
 		.msg_namelen = sizeof(src),
@@ -704,7 +747,46 @@ static bool radius_receive(private_tnc_pdp_t *this, int fd, watcher_event_t even
 		if (request->verify(request, NULL, this->secret, this->hasher,
 										   this->signer))
 		{
-			process_eap(this, request, source);
+			id = request->get_identifier(request);
+			now = time(NULL);
+
+			enumerator = this->clients->create_enumerator(this->clients);
+			while (enumerator->enumerate(enumerator, &client))
+			{
+				stale = client->last_time < now - RADIUS_RETRANSMIT_TIMEOUT;
+
+				if (source->equals(source, client->host))
+				{
+					retransmission = !stale && client->last_id == id;
+					client->last_id = id;
+					client->last_time = now;
+					found = TRUE;
+				}
+				else if (stale)
+				{
+					this->clients->remove_at(this->clients, enumerator);
+					free_client_entry(client);
+				}
+			}
+			enumerator->destroy(enumerator);
+
+			if (!found)
+			{
+				client = malloc_thing(client_entry_t);
+				client->host = source->clone(source);
+				client->last_id = id;
+				client->last_time = now;
+				this->clients->insert_last(this->clients, client);
+			}
+			if (retransmission)
+			{
+				DBG1(DBG_CFG, "ignoring RADIUS Access-Request 0x%02x, "
+							  "already processing", id);
+			}
+			else
+			{
+				process_eap(this, request, source);
+			}
 		}
 		request->destroy(request);
 	}
@@ -739,6 +821,10 @@ METHOD(tnc_pdp_t, destroy, void,
 		lib->watcher->remove(lib->watcher, this->radius_ipv6);
 		close(this->radius_ipv6);
 	}
+	if (this->clients)
+	{
+		this->clients->destroy_function(this->clients, (void*)free_client_entry);
+	}
 	DESTROY_IF(this->server);
 	DESTROY_IF(this->signer);
 	DESTROY_IF(this->hasher);
@@ -843,6 +929,7 @@ tnc_pdp_t *tnc_pdp_create(void)
 		this->radius_ipv4 = open_udp_socket(AF_INET,  radius_port);
 		this->radius_ipv6 = open_udp_socket(AF_INET6, radius_port);
 		this->secret = chunk_from_str(secret);
+		this->clients = linked_list_create();
 		this->type = eap_type_from_string(eap_type_str);
 		this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
 		this->signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_MD5_128);
diff --git a/src/libcharon/plugins/uci/Makefile.am b/src/libcharon/plugins/uci/Makefile.am
index 1fcd9ed..134ced0 100644
--- a/src/libcharon/plugins/uci/Makefile.am
+++ b/src/libcharon/plugins/uci/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-uci.la
diff --git a/src/libcharon/plugins/uci/Makefile.in b/src/libcharon/plugins/uci/Makefile.in
index 8c38cea..948db7e 100644
--- a/src/libcharon/plugins/uci/Makefile.in
+++ b/src/libcharon/plugins/uci/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-uci.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-uci.la
diff --git a/src/libcharon/plugins/unit_tester/Makefile.am b/src/libcharon/plugins/unit_tester/Makefile.am
index 21cf08c..b7f8fc3 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.am
+++ b/src/libcharon/plugins/unit_tester/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-unit-tester.la
diff --git a/src/libcharon/plugins/unit_tester/Makefile.in b/src/libcharon/plugins/unit_tester/Makefile.in
index 165590d..6e4dbff 100644
--- a/src/libcharon/plugins/unit_tester/Makefile.in
+++ b/src/libcharon/plugins/unit_tester/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ 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@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-unit-tester.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-unit-tester.la
diff --git a/src/libcharon/plugins/unity/Makefile.am b/src/libcharon/plugins/unity/Makefile.am
index b50dc9a..38923e0 100644
--- a/src/libcharon/plugins/unity/Makefile.am
+++ b/src/libcharon/plugins/unity/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-unity.la
diff --git a/src/libcharon/plugins/unity/Makefile.in b/src/libcharon/plugins/unity/Makefile.in
index efb7e95..4d411f6 100644
--- a/src/libcharon/plugins/unity/Makefile.in
+++ b/src/libcharon/plugins/unity/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-unity.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-unity.la
diff --git a/src/libcharon/plugins/updown/Makefile.am b/src/libcharon/plugins/updown/Makefile.am
index a359094..f03f474 100644
--- a/src/libcharon/plugins/updown/Makefile.am
+++ b/src/libcharon/plugins/updown/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-updown.la
diff --git a/src/libcharon/plugins/updown/Makefile.in b/src/libcharon/plugins/updown/Makefile.in
index 36cf78e..b377110 100644
--- a/src/libcharon/plugins/updown/Makefile.in
+++ b/src/libcharon/plugins/updown/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-updown.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-updown.la
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 2c3f932..200f298 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -344,12 +344,12 @@ METHOD(listener_t, child_updown, bool,
 				"PLUTO_UNIQUEID='%u' "
 				"PLUTO_ME='%H' "
 				"PLUTO_MY_ID='%Y' "
-				"PLUTO_MY_CLIENT='%H/%u' "
+				"PLUTO_MY_CLIENT='%+H/%u' "
 				"PLUTO_MY_PORT='%u' "
 				"PLUTO_MY_PROTOCOL='%u' "
 				"PLUTO_PEER='%H' "
 				"PLUTO_PEER_ID='%Y' "
-				"PLUTO_PEER_CLIENT='%H/%u' "
+				"PLUTO_PEER_CLIENT='%+H/%u' "
 				"PLUTO_PEER_PORT='%u' "
 				"PLUTO_PEER_PROTOCOL='%u' "
 				"%s"
diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am
new file mode 100644
index 0000000..7e459c5
--- /dev/null
+++ b/src/libcharon/plugins/vici/Makefile.am
@@ -0,0 +1,69 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libhydra \
+	-I$(top_srcdir)/src/libcharon \
+	-DIPSEC_PIDDIR=\"${piddir}\"
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-vici.la
+else
+plugin_LTLIBRARIES = libstrongswan-vici.la
+endif
+
+libstrongswan_vici_la_SOURCES = \
+	vici_socket.h vici_socket.c \
+	vici_message.h vici_message.c \
+	vici_builder.h vici_builder.c \
+	vici_dispatcher.h vici_dispatcher.c \
+	vici_query.h vici_query.c \
+	vici_control.h vici_control.c \
+	vici_config.h vici_config.c \
+	vici_cred.h vici_cred.c \
+	vici_attribute.h vici_attribute.c \
+	vici_logger.h vici_logger.c \
+	vici_plugin.h vici_plugin.c
+
+libstrongswan_vici_la_LDFLAGS = -module -avoid-version
+
+
+EXTRA_DIST = README.md
+
+
+ipseclib_LTLIBRARIES = libvici.la
+
+libvici_la_SOURCES = \
+	vici_message.c vici_message.h \
+	vici_builder.c vici_builder.h \
+	libvici.c libvici.h
+
+libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+
+TESTS = vici_tests
+
+check_PROGRAMS = $(TESTS)
+
+vici_tests_SOURCES = \
+	suites/test_socket.c \
+	suites/test_message.c \
+	suites/test_request.c \
+	suites/test_event.c \
+	vici_socket.c \
+	vici_message.c \
+	vici_builder.c \
+	vici_dispatcher.c \
+	libvici.c \
+	vici_tests.h vici_tests.c
+
+vici_tests_CFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libstrongswan/tests \
+	@COVERAGE_CFLAGS@
+
+vici_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+vici_tests_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in
new file mode 100644
index 0000000..e0a6a1b
--- /dev/null
+++ b/src/libcharon/plugins/vici/Makefile.in
@@ -0,0 +1,1183 @@
+# 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 = vici_tests$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1)
+subdir = src/libcharon/plugins/vici
+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)" "$(DESTDIR)$(plugindir)"
+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_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@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libstrongswan_vici_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_vici_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_vici_la_rpath = -rpath $(plugindir)
+ at MONOLITHIC_TRUE@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
+libvici_la_OBJECTS = $(am_libvici_la_OBJECTS)
+am__EXEEXT_1 = vici_tests$(EXEEXT)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_vici_tests_OBJECTS = suites/vici_tests-test_socket.$(OBJEXT) \
+	suites/vici_tests-test_message.$(OBJEXT) \
+	suites/vici_tests-test_request.$(OBJEXT) \
+	suites/vici_tests-test_event.$(OBJEXT) \
+	vici_tests-vici_socket.$(OBJEXT) \
+	vici_tests-vici_message.$(OBJEXT) \
+	vici_tests-vici_builder.$(OBJEXT) \
+	vici_tests-vici_dispatcher.$(OBJEXT) \
+	vici_tests-libvici.$(OBJEXT) vici_tests-vici_tests.$(OBJEXT)
+vici_tests_OBJECTS = $(am_vici_tests_OBJECTS)
+vici_tests_DEPENDENCIES =  \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la
+vici_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(vici_tests_CFLAGS) \
+	$(CFLAGS) $(vici_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_vici_la_SOURCES) $(libvici_la_SOURCES) \
+	$(vici_tests_SOURCES)
+DIST_SOURCES = $(libstrongswan_vici_la_SOURCES) $(libvici_la_SOURCES) \
+	$(vici_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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 \
+	-DIPSEC_PIDDIR=\"${piddir}\"
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-vici.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-vici.la
+libstrongswan_vici_la_SOURCES = \
+	vici_socket.h vici_socket.c \
+	vici_message.h vici_message.c \
+	vici_builder.h vici_builder.c \
+	vici_dispatcher.h vici_dispatcher.c \
+	vici_query.h vici_query.c \
+	vici_control.h vici_control.c \
+	vici_config.h vici_config.c \
+	vici_cred.h vici_cred.c \
+	vici_attribute.h vici_attribute.c \
+	vici_logger.h vici_logger.c \
+	vici_plugin.h vici_plugin.c
+
+libstrongswan_vici_la_LDFLAGS = -module -avoid-version
+EXTRA_DIST = README.md
+ipseclib_LTLIBRARIES = libvici.la
+libvici_la_SOURCES = \
+	vici_message.c vici_message.h \
+	vici_builder.c vici_builder.h \
+	libvici.c libvici.h
+
+libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+vici_tests_SOURCES = \
+	suites/test_socket.c \
+	suites/test_message.c \
+	suites/test_request.c \
+	suites/test_event.c \
+	vici_socket.c \
+	vici_message.c \
+	vici_builder.c \
+	vici_dispatcher.c \
+	libvici.c \
+	vici_tests.h vici_tests.c
+
+vici_tests_CFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libstrongswan/tests \
+	@COVERAGE_CFLAGS@
+
+vici_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+vici_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/vici/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libcharon/plugins/vici/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}; \
+	}
+
+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-vici.la: $(libstrongswan_vici_la_OBJECTS) $(libstrongswan_vici_la_DEPENDENCIES) $(EXTRA_libstrongswan_vici_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_vici_la_LINK) $(am_libstrongswan_vici_la_rpath) $(libstrongswan_vici_la_OBJECTS) $(libstrongswan_vici_la_LIBADD) $(LIBS)
+
+libvici.la: $(libvici_la_OBJECTS) $(libvici_la_DEPENDENCIES) $(EXTRA_libvici_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(LINK) -rpath $(ipseclibdir) $(libvici_la_OBJECTS) $(libvici_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/vici_tests-test_socket.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
+suites/vici_tests-test_message.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
+suites/vici_tests-test_request.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
+suites/vici_tests-test_event.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
+
+vici_tests$(EXEEXT): $(vici_tests_OBJECTS) $(vici_tests_DEPENDENCIES) $(EXTRA_vici_tests_DEPENDENCIES) 
+	@rm -f vici_tests$(EXEEXT)
+	$(AM_V_CCLD)$(vici_tests_LINK) $(vici_tests_OBJECTS) $(vici_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)/libvici.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_attribute.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_builder.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_config.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_control.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_cred.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_dispatcher.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_logger.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_message.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_plugin.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_query.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_socket.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_tests-libvici.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_tests-vici_builder.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_tests-vici_dispatcher.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_tests-vici_message.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_tests-vici_socket.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/vici_tests-vici_tests.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/vici_tests-test_event.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/vici_tests-test_message.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/vici_tests-test_request.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/vici_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 $@ $<
+
+suites/vici_tests-test_socket.o: suites/test_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_socket.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_socket.Tpo -c -o suites/vici_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)/vici_tests-test_socket.Tpo suites/$(DEPDIR)/vici_tests-test_socket.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_socket.c' object='suites/vici_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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_socket.o `test -f 'suites/test_socket.c' || echo '$(srcdir)/'`suites/test_socket.c
+
+suites/vici_tests-test_socket.obj: suites/test_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_socket.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_socket.Tpo -c -o suites/vici_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)/vici_tests-test_socket.Tpo suites/$(DEPDIR)/vici_tests-test_socket.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_socket.c' object='suites/vici_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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_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`
+
+suites/vici_tests-test_message.o: suites/test_message.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_message.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_message.Tpo -c -o suites/vici_tests-test_message.o `test -f 'suites/test_message.c' || echo '$(srcdir)/'`suites/test_message.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_message.Tpo suites/$(DEPDIR)/vici_tests-test_message.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_message.c' object='suites/vici_tests-test_message.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_message.o `test -f 'suites/test_message.c' || echo '$(srcdir)/'`suites/test_message.c
+
+suites/vici_tests-test_message.obj: suites/test_message.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_message.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_message.Tpo -c -o suites/vici_tests-test_message.obj `if test -f 'suites/test_message.c'; then $(CYGPATH_W) 'suites/test_message.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_message.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_message.Tpo suites/$(DEPDIR)/vici_tests-test_message.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_message.c' object='suites/vici_tests-test_message.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_message.obj `if test -f 'suites/test_message.c'; then $(CYGPATH_W) 'suites/test_message.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_message.c'; fi`
+
+suites/vici_tests-test_request.o: suites/test_request.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_request.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_request.Tpo -c -o suites/vici_tests-test_request.o `test -f 'suites/test_request.c' || echo '$(srcdir)/'`suites/test_request.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_request.Tpo suites/$(DEPDIR)/vici_tests-test_request.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_request.c' object='suites/vici_tests-test_request.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_request.o `test -f 'suites/test_request.c' || echo '$(srcdir)/'`suites/test_request.c
+
+suites/vici_tests-test_request.obj: suites/test_request.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_request.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_request.Tpo -c -o suites/vici_tests-test_request.obj `if test -f 'suites/test_request.c'; then $(CYGPATH_W) 'suites/test_request.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_request.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_request.Tpo suites/$(DEPDIR)/vici_tests-test_request.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_request.c' object='suites/vici_tests-test_request.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_request.obj `if test -f 'suites/test_request.c'; then $(CYGPATH_W) 'suites/test_request.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_request.c'; fi`
+
+suites/vici_tests-test_event.o: suites/test_event.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_event.o -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_event.Tpo -c -o suites/vici_tests-test_event.o `test -f 'suites/test_event.c' || echo '$(srcdir)/'`suites/test_event.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_event.Tpo suites/$(DEPDIR)/vici_tests-test_event.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_event.c' object='suites/vici_tests-test_event.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_event.o `test -f 'suites/test_event.c' || echo '$(srcdir)/'`suites/test_event.c
+
+suites/vici_tests-test_event.obj: suites/test_event.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT suites/vici_tests-test_event.obj -MD -MP -MF suites/$(DEPDIR)/vici_tests-test_event.Tpo -c -o suites/vici_tests-test_event.obj `if test -f 'suites/test_event.c'; then $(CYGPATH_W) 'suites/test_event.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_event.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/vici_tests-test_event.Tpo suites/$(DEPDIR)/vici_tests-test_event.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_event.c' object='suites/vici_tests-test_event.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o suites/vici_tests-test_event.obj `if test -f 'suites/test_event.c'; then $(CYGPATH_W) 'suites/test_event.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_event.c'; fi`
+
+vici_tests-vici_socket.o: vici_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_socket.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_socket.Tpo -c -o vici_tests-vici_socket.o `test -f 'vici_socket.c' || echo '$(srcdir)/'`vici_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_socket.Tpo $(DEPDIR)/vici_tests-vici_socket.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_socket.c' object='vici_tests-vici_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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_socket.o `test -f 'vici_socket.c' || echo '$(srcdir)/'`vici_socket.c
+
+vici_tests-vici_socket.obj: vici_socket.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_socket.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_socket.Tpo -c -o vici_tests-vici_socket.obj `if test -f 'vici_socket.c'; then $(CYGPATH_W) 'vici_socket.c'; else $(CYGPATH_W) '$(srcdir)/vici_socket.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_socket.Tpo $(DEPDIR)/vici_tests-vici_socket.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_socket.c' object='vici_tests-vici_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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_socket.obj `if test -f 'vici_socket.c'; then $(CYGPATH_W) 'vici_socket.c'; else $(CYGPATH_W) '$(srcdir)/vici_socket.c'; fi`
+
+vici_tests-vici_message.o: vici_message.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_message.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_message.Tpo -c -o vici_tests-vici_message.o `test -f 'vici_message.c' || echo '$(srcdir)/'`vici_message.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_message.Tpo $(DEPDIR)/vici_tests-vici_message.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_message.c' object='vici_tests-vici_message.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_message.o `test -f 'vici_message.c' || echo '$(srcdir)/'`vici_message.c
+
+vici_tests-vici_message.obj: vici_message.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_message.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_message.Tpo -c -o vici_tests-vici_message.obj `if test -f 'vici_message.c'; then $(CYGPATH_W) 'vici_message.c'; else $(CYGPATH_W) '$(srcdir)/vici_message.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_message.Tpo $(DEPDIR)/vici_tests-vici_message.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_message.c' object='vici_tests-vici_message.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_message.obj `if test -f 'vici_message.c'; then $(CYGPATH_W) 'vici_message.c'; else $(CYGPATH_W) '$(srcdir)/vici_message.c'; fi`
+
+vici_tests-vici_builder.o: vici_builder.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_builder.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_builder.Tpo -c -o vici_tests-vici_builder.o `test -f 'vici_builder.c' || echo '$(srcdir)/'`vici_builder.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_builder.Tpo $(DEPDIR)/vici_tests-vici_builder.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_builder.c' object='vici_tests-vici_builder.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_builder.o `test -f 'vici_builder.c' || echo '$(srcdir)/'`vici_builder.c
+
+vici_tests-vici_builder.obj: vici_builder.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_builder.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_builder.Tpo -c -o vici_tests-vici_builder.obj `if test -f 'vici_builder.c'; then $(CYGPATH_W) 'vici_builder.c'; else $(CYGPATH_W) '$(srcdir)/vici_builder.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_builder.Tpo $(DEPDIR)/vici_tests-vici_builder.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_builder.c' object='vici_tests-vici_builder.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_builder.obj `if test -f 'vici_builder.c'; then $(CYGPATH_W) 'vici_builder.c'; else $(CYGPATH_W) '$(srcdir)/vici_builder.c'; fi`
+
+vici_tests-vici_dispatcher.o: vici_dispatcher.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_dispatcher.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_dispatcher.Tpo -c -o vici_tests-vici_dispatcher.o `test -f 'vici_dispatcher.c' || echo '$(srcdir)/'`vici_dispatcher.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_dispatcher.Tpo $(DEPDIR)/vici_tests-vici_dispatcher.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_dispatcher.c' object='vici_tests-vici_dispatcher.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_dispatcher.o `test -f 'vici_dispatcher.c' || echo '$(srcdir)/'`vici_dispatcher.c
+
+vici_tests-vici_dispatcher.obj: vici_dispatcher.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_dispatcher.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_dispatcher.Tpo -c -o vici_tests-vici_dispatcher.obj `if test -f 'vici_dispatcher.c'; then $(CYGPATH_W) 'vici_dispatcher.c'; else $(CYGPATH_W) '$(srcdir)/vici_dispatcher.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_dispatcher.Tpo $(DEPDIR)/vici_tests-vici_dispatcher.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_dispatcher.c' object='vici_tests-vici_dispatcher.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_dispatcher.obj `if test -f 'vici_dispatcher.c'; then $(CYGPATH_W) 'vici_dispatcher.c'; else $(CYGPATH_W) '$(srcdir)/vici_dispatcher.c'; fi`
+
+vici_tests-libvici.o: libvici.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-libvici.o -MD -MP -MF $(DEPDIR)/vici_tests-libvici.Tpo -c -o vici_tests-libvici.o `test -f 'libvici.c' || echo '$(srcdir)/'`libvici.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-libvici.Tpo $(DEPDIR)/vici_tests-libvici.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='libvici.c' object='vici_tests-libvici.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-libvici.o `test -f 'libvici.c' || echo '$(srcdir)/'`libvici.c
+
+vici_tests-libvici.obj: libvici.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-libvici.obj -MD -MP -MF $(DEPDIR)/vici_tests-libvici.Tpo -c -o vici_tests-libvici.obj `if test -f 'libvici.c'; then $(CYGPATH_W) 'libvici.c'; else $(CYGPATH_W) '$(srcdir)/libvici.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-libvici.Tpo $(DEPDIR)/vici_tests-libvici.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='libvici.c' object='vici_tests-libvici.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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-libvici.obj `if test -f 'libvici.c'; then $(CYGPATH_W) 'libvici.c'; else $(CYGPATH_W) '$(srcdir)/libvici.c'; fi`
+
+vici_tests-vici_tests.o: vici_tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_tests.o -MD -MP -MF $(DEPDIR)/vici_tests-vici_tests.Tpo -c -o vici_tests-vici_tests.o `test -f 'vici_tests.c' || echo '$(srcdir)/'`vici_tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_tests.Tpo $(DEPDIR)/vici_tests-vici_tests.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_tests.c' object='vici_tests-vici_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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_tests.o `test -f 'vici_tests.c' || echo '$(srcdir)/'`vici_tests.c
+
+vici_tests-vici_tests.obj: vici_tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(vici_tests_CFLAGS) $(CFLAGS) -MT vici_tests-vici_tests.obj -MD -MP -MF $(DEPDIR)/vici_tests-vici_tests.Tpo -c -o vici_tests-vici_tests.obj `if test -f 'vici_tests.c'; then $(CYGPATH_W) 'vici_tests.c'; else $(CYGPATH_W) '$(srcdir)/vici_tests.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/vici_tests-vici_tests.Tpo $(DEPDIR)/vici_tests-vici_tests.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='vici_tests.c' object='vici_tests-vici_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) $(vici_tests_CFLAGS) $(CFLAGS) -c -o vici_tests-vici_tests.obj `if test -f 'vici_tests.c'; then $(CYGPATH_W) 'vici_tests.c'; else $(CYGPATH_W) '$(srcdir)/vici_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 $(LTLIBRARIES)
+installdirs:
+	for dir in "$(DESTDIR)$(ipseclibdir)" "$(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-ipseclibLTLIBRARIES \
+	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-ipseclibLTLIBRARIES 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-ipseclibLTLIBRARIES \
+	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-ipseclibLTLIBRARIES \
+	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-ipseclibLTLIBRARIES \
+	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-ipseclibLTLIBRARIES 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/vici/README.md b/src/libcharon/plugins/vici/README.md
new file mode 100644
index 0000000..aeabbbd
--- /dev/null
+++ b/src/libcharon/plugins/vici/README.md
@@ -0,0 +1,176 @@
+# The Versatile IKE Control Interface (VICI) protocol #
+
+The vici plugin implements the server side of an IPC protocol to configure,
+monitor and control the IKE daemon charon. It uses request/response and event
+messages to communicate over a reliable stream based transport.
+
+## Transport protocol ##
+
+To provide the service, the plugin opens a listening socket using a reliable,
+stream based transport. charon relies on the different stream service
+abstractions provided by libstrongswan, such as TCP and UNIX sockets.
+
+A client connects to this service to access functionality. It may send an
+arbitrary number of packets over the connection before closing it.
+
+To exchange data, the transport protocol is segmented into byte sequences.
+Each byte sequence is prefixed by a 32-bit length header in network order,
+followed by the data. The maximum segment length is currently limited to 512KB
+of data, and the length field contains the length of the data only, not
+including the length field itself.
+
+The order of byte sequences must be strict, byte sequences must arrive in the
+same order as sent.
+
+## Packet layer ##
+
+Within the byte sequences defined by the transport layer, both the client
+and the server can exchange packets. The type of packet defines its structure
+and purpose. The packet type is a 8-bit identifier, and is the first byte
+in a transport layer byte sequence. The length of the packet is given by the
+transport layer.
+
+While a packet type may define the format of the wrapped data freely, currently
+all types either contain a name, a message or both. The following packet types
+are currently defined:
+
+* _CMD_REQUEST = 0_: A named request message
+* _CMD_RESPONSE = 1_: An unnamed response message for a request
+* _CMD_UNKNOWN = 2_: An unnamed response if requested command is unknown
+* _EVENT_REGISTER = 3_: A named event registration request
+* _EVENT_UNREGISTER = 4_: A named event deregistration request
+* _EVENT_CONFIRM = 5_: An unnamed response for successful event (de-)registration
+* _EVENT_UNKNOWN = 6_: A unnamed response if event (de-)registration failed
+* _EVENT = 7_: A named event message
+
+For packets having a named type, after the packet type an 8-bit length header
+of the name follows, indicating the string length in bytes of the name tag, not
+including the length field itself. The name is an ASCII string that is not
+null-terminated.
+
+The rest of the packet forms the exchanged message, the length is determined
+by the transport byte sequence length, subtracting the packet type and
+the optional name tag in some messages.
+
+### Commands ###
+
+Commands are currently always requested by the client. The server replies with
+a response, or with a CMD_UNKNOWN failure message to let the client know
+that it does not have a handler for such a command. There is no sequence number
+to associate responses to requests, so only one command can be active at
+a time on a single connection.
+
+### Events ###
+
+To receive event messages, the client explicitly registers for events by name,
+and also unregisters if it does not want to receive events of the named kind
+anymore. The server confirms event registration using EVENT_CONFIRM, or
+indicates that there is no such event source with EVENT_UNKNOWN.
+
+Events may get raised at any time while registered, even during an active
+request command. This mechanism is used to feed continuous data during a request,
+for example.
+
+## Message format ##
+
+The defined packet types optionally wrap a message with additional data.
+Messages are currently used in CMD_REQUEST/CMD_RESPONSE, and in EVENT packets.
+A message uses a hierarchial tree of sections. Each section (or the implicit
+root section) contains an arbitrary set of key/value pairs, lists and
+sub-sections. The length of a message is not part of the message itself, but
+the wrapping layer, usually calculated from the transport byte sequence length.
+
+The message encoding consists of a sequence of elements. Each element starts
+with the element type, optionally followed by an element name and/or an element
+value. Currently the following message element types are defined:
+
+* _SECTION_START = 0_: Begin a new section having a name
+* _SECTION_END = 1_: End a previously started section
+* _KEY_VALUE = 2_: Define a value for a named key in the current section
+* _LIST_START = 3_: Begin a named list for list items
+* _LIST_ITEM = 4_: Define an unnamed item value in the current list
+* _LIST_END = 5_: End a previously started list
+
+Types are encoded as 8-bit values. Types having a name (SECTION_START,
+KEY_VALUE and LIST_START) have an ASCII string following the type, which itself
+uses an 8-bit length header. The string must not be null-terminated, the string
+length does not include the length field itself.
+
+Types having a value (KEY_VALUE and LIST_ITEM) have a raw blob sequence,
+prefixed with a 16-bit network order length. The blob follows the type or the
+name tag if available, the length defined by the length field does not include
+the length field itself.
+
+The interpretation of any value is not defined by the message format; it can
+take arbitrary blobs. The application may specify types for specific keys, such
+as strings or integer representations.
+
+### Sections ###
+
+Sections may be opened in the implicit root section, or any previously section.
+They can be nested to arbitrary levels. A SECTION_END marker always closes
+the last opened section; SECTION_START and SECTION_END items must be balanced
+in a valid message.
+
+### Key/Values ###
+
+Key/Value pair elements may appear in the implicit root section or any explicit
+sub-section at any level. Key names must be unique in the current section, use
+lists to define multiple values for a key. Key/values may not appear in lists,
+use a sub-section instead.
+
+### Lists ###
+
+Lists may appear at the same locations as Key/Values, and may not be nested.
+Only a single list may be opened at the same time, and all lists must be closed
+in valid messages. After opening a list, only list items may appear before the
+list closing element. Empty lists are allowed, list items may appear within
+lists only.
+
+### Encoding example ###
+
+Consider the following structure using pseudo-markup for this example:
+
+	key1 = value1
+	section1 = {
+		sub-section = {
+			key2 = value2
+		}
+		list1 = [ item1, item2 ]
+	}
+
+The example above reprensents a valid tree structure, that gets encoded as
+the following C array:
+
+	char msg[] = {
+		/* key1 = value1 */
+		2, 4,'k','e','y','1', 0,6,'v','a','l','u','e','1',
+		/* section1 */
+		0, 8,'s','e','c','t','i','o','n','1',
+		/* sub-section */
+		0, 11,'s','u','b','-','s','e','c','t','i','o','n',
+		/* key2 = value2 */
+		2, 4,'k','e','y','2', 0,6,'v','a','l','u','e','2',
+		/* sub-section end */
+		1,
+		/* list1 */
+		3, 5, 'l','i','s','t','1',
+		/* item1 */
+		4, 0,5,'i','t','e','m','1',
+		/* item2 */
+		4, 0,5,'i','t','e','m','2',
+		/* list1 end */
+		5,
+		/* section1 end */
+		1,
+	};
+
+# libvici C client library #
+
+libvici is the reference implementation of a C client library implementing
+the vici protocol. It builds upon libstrongswan, but provides a stable API
+to implement client applications in the C programming language. libvici uses
+the libstrongswan thread pool to deliver event messages asynchronously.
+
+More information about the libvici API is available in the libvici.h header
+file.
diff --git a/src/libcharon/plugins/vici/libvici.c b/src/libcharon/plugins/vici/libvici.c
new file mode 100644
index 0000000..a2cbb30
--- /dev/null
+++ b/src/libcharon/plugins/vici/libvici.c
@@ -0,0 +1,764 @@
+/*
+ * 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 "libvici.h"
+#include "vici_builder.h"
+#include "vici_dispatcher.h"
+#include "vici_socket.h"
+
+#include <library.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <collections/hashtable.h>
+
+#include <errno.h>
+
+/**
+ * Event registration
+ */
+typedef struct {
+	/** name of event */
+	char *name;
+	/** callback function */
+	vici_event_cb_t cb;
+	/** user data for callback */
+	void *user;
+} event_t;
+
+/**
+ * Wait state signaled by asynchronous on_read callback
+ */
+typedef enum {
+	WAIT_IDLE = 0,
+	WAIT_SUCCESS,
+	WAIT_FAILURE,
+	WAIT_READ_ERROR,
+} wait_state_t;
+
+/**
+ * Private vici connection contex.
+ */
+struct vici_conn_t {
+	/** connection stream */
+	stream_t *stream;
+	/** event registrations, as char* => event_t */
+	hashtable_t *events;
+	/** connection lock */
+	mutex_t *mutex;
+	/** condvar to signal incoming response */
+	condvar_t *cond;
+	/** queued response message */
+	chunk_t queue;
+	/** asynchronous read error */
+	int error;
+	/** wait state */
+	wait_state_t wait;
+};
+
+/**
+ * Private vici request message.
+ */
+struct vici_req_t {
+	/** connection context */
+	vici_conn_t *conn;
+	/** name of request message */
+	char *name;
+	/** message builder */
+	vici_builder_t *b;
+};
+
+/**
+ * Private vici response/event message.
+ */
+struct vici_res_t {
+	/** response message */
+	vici_message_t *message;
+	/** allocated strings */
+	linked_list_t *strings;
+	/** item enumerator */
+	enumerator_t *enumerator;
+	/** currently enumerating type */
+	vici_type_t type;
+	/** currently enumerating name */
+	char *name;
+	/** currently enumerating value */
+	chunk_t value;
+	/** section nesting level of callback parser */
+	int level;
+};
+
+/**
+ * Signal wait result for waiting user thread
+ */
+static bool wait_result(vici_conn_t *conn, wait_state_t wait)
+{
+	conn->mutex->lock(conn->mutex);
+	conn->wait = wait;
+	conn->mutex->unlock(conn->mutex);
+	conn->cond->signal(conn->cond);
+	return FALSE;
+}
+
+/**
+ * Signal wait error result for waiting user thread
+ */
+static bool read_error(vici_conn_t *conn, int err)
+{
+	conn->error = err;
+	return wait_result(conn, WAIT_READ_ERROR);
+}
+
+/**
+ * Handle a command response message
+ */
+static bool handle_response(vici_conn_t *conn, u_int32_t len)
+{
+	chunk_t buf;
+
+	buf = chunk_alloc(len);
+	if (!conn->stream->read_all(conn->stream, buf.ptr, buf.len))
+	{
+		free(buf.ptr);
+		return read_error(conn, errno);
+	}
+	conn->queue = buf;
+	return wait_result(conn, WAIT_SUCCESS);
+}
+
+/**
+ * Dispatch received event message
+ */
+static bool handle_event(vici_conn_t *conn, u_int32_t len)
+{
+	vici_message_t *message;
+	event_t *event;
+	u_int8_t namelen;
+	char name[257], *buf;
+
+	if (len < sizeof(namelen))
+	{
+		return read_error(conn, EBADMSG);
+	}
+	if (!conn->stream->read_all(conn->stream, &namelen, sizeof(namelen)))
+	{
+		return read_error(conn, errno);
+	}
+	if (namelen > len - sizeof(namelen))
+	{
+		return read_error(conn, EBADMSG);
+	}
+	if (!conn->stream->read_all(conn->stream, name, namelen))
+	{
+		return read_error(conn, errno);
+	}
+	name[namelen] = '\0';
+	len -= sizeof(namelen) + namelen;
+	buf = malloc(len);
+	if (!conn->stream->read_all(conn->stream, buf, len))
+	{
+		free(buf);
+		return read_error(conn, errno);
+	}
+	message = vici_message_create_from_data(chunk_create(buf, len), TRUE);
+
+	conn->mutex->lock(conn->mutex);
+	event = conn->events->get(conn->events, name);
+	if (event)
+	{
+		vici_res_t res = {
+			.message = message,
+			.enumerator = message->create_enumerator(message),
+			.strings = linked_list_create(),
+		};
+
+		event->cb(event->user, name, &res);
+
+		res.enumerator->destroy(res.enumerator);
+		res.strings->destroy_function(res.strings, free);
+	}
+	conn->mutex->unlock(conn->mutex);
+
+	message->destroy(message);
+
+	return TRUE;
+}
+
+CALLBACK(on_read, bool,
+	vici_conn_t *conn, stream_t *stream)
+{
+	u_int32_t len;
+	u_int8_t op;
+	ssize_t hlen;
+
+	hlen = stream->read(stream, &len, sizeof(len), FALSE);
+	if (hlen <= 0)
+	{
+		if (errno == EWOULDBLOCK)
+		{
+			return TRUE;
+		}
+		return read_error(conn, errno);
+	}
+	if (hlen < sizeof(len))
+	{
+		if (!stream->read_all(stream, ((void*)&len) + hlen, sizeof(len) - hlen))
+		{
+			return read_error(conn, errno);
+		}
+	}
+
+	len = ntohl(len);
+	if (len > VICI_MESSAGE_SIZE_MAX)
+	{
+		return read_error(conn, EBADMSG);
+	}
+	if (len-- < sizeof(op))
+	{
+		return read_error(conn, EBADMSG);
+	}
+	if (!stream->read_all(stream, &op, sizeof(op)))
+	{
+		return read_error(conn, errno);
+	}
+	switch (op)
+	{
+		case VICI_EVENT:
+			return handle_event(conn, len);
+		case VICI_CMD_RESPONSE:
+			return handle_response(conn, len);
+		case VICI_EVENT_CONFIRM:
+			return wait_result(conn, WAIT_SUCCESS);
+		case VICI_CMD_UNKNOWN:
+		case VICI_EVENT_UNKNOWN:
+			return wait_result(conn, WAIT_FAILURE);
+		case VICI_CMD_REQUEST:
+		case VICI_EVENT_REGISTER:
+		case VICI_EVENT_UNREGISTER:
+		default:
+			return read_error(conn, EBADMSG);
+	}
+}
+
+vici_conn_t* vici_connect(char *uri)
+{
+	vici_conn_t *conn;
+	stream_t *stream;
+
+	stream = lib->streams->connect(lib->streams, uri ?: VICI_DEFAULT_URI);
+	if (!stream)
+	{
+		return NULL;
+	}
+
+	INIT(conn,
+		.stream = stream,
+		.events = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.cond = condvar_create(CONDVAR_TYPE_DEFAULT),
+	);
+
+	stream->on_read(stream, on_read, conn);
+
+	return conn;
+}
+
+void vici_disconnect(vici_conn_t *conn)
+{
+	enumerator_t *enumerator;
+	event_t *event;
+
+	conn->stream->destroy(conn->stream);
+	enumerator = conn->events->create_enumerator(conn->events);
+	while (enumerator->enumerate(enumerator, NULL, &event))
+	{
+		free(event->name);
+		free(event);
+	}
+	enumerator->destroy(enumerator);
+	conn->events->destroy(conn->events);
+	conn->mutex->destroy(conn->mutex);
+	conn->cond->destroy(conn->cond);
+	free(conn);
+}
+
+vici_req_t* vici_begin(char *name)
+{
+	vici_req_t *req;
+
+	INIT(req,
+		.name = strdup(name),
+		.b = vici_builder_create(),
+	);
+
+	return req;
+}
+
+void vici_begin_section(vici_req_t *req, char *name)
+{
+	req->b->add(req->b, VICI_SECTION_START, name);
+}
+
+void vici_end_section(vici_req_t *req)
+{
+	req->b->add(req->b, VICI_SECTION_END);
+}
+
+void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len)
+{
+	req->b->add(req->b, VICI_KEY_VALUE, key, chunk_create(buf, len));
+}
+
+void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	req->b->vadd_kv(req->b, key, fmt, args);
+	va_end(args);
+}
+
+void vici_begin_list(vici_req_t *req, char *name)
+{
+	req->b->add(req->b, VICI_LIST_START, name);
+}
+
+void vici_add_list_item(vici_req_t *req, void *buf, int len)
+{
+	req->b->add(req->b, VICI_LIST_ITEM, chunk_create(buf, len));
+}
+
+void vici_add_list_itemf(vici_req_t *req, char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	req->b->vadd_li(req->b, fmt, args);
+	va_end(args);
+}
+
+void vici_end_list(vici_req_t *req)
+{
+	req->b->add(req->b, VICI_LIST_END);
+}
+
+vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn)
+{
+	vici_message_t *message;
+	vici_res_t *res;
+	chunk_t data;
+	u_int32_t len;
+	u_int8_t namelen, op;
+
+	message = req->b->finalize(req->b);
+	if (!message)
+	{
+		errno = EINVAL;
+		return NULL;
+	}
+
+	op = VICI_CMD_REQUEST;
+	namelen = strlen(req->name);
+	data = message->get_encoding(message);
+	len = htonl(sizeof(op) + sizeof(namelen) + namelen + data.len);
+
+	if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
+		!conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
+		!conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
+		!conn->stream->write_all(conn->stream, req->name, namelen) ||
+		!conn->stream->write_all(conn->stream, data.ptr, data.len))
+	{
+		free(req->name);
+		free(req);
+		message->destroy(message);
+		return NULL;
+	}
+	free(req->name);
+	free(req);
+	message->destroy(message);
+
+	message = NULL;
+	conn->mutex->lock(conn->mutex);
+	while (conn->wait == WAIT_IDLE)
+	{
+		conn->cond->wait(conn->cond, conn->mutex);
+	}
+	switch (conn->wait)
+	{
+		case WAIT_SUCCESS:
+			message = vici_message_create_from_data(conn->queue, TRUE);
+			conn->queue = chunk_empty;
+			break;
+		case WAIT_READ_ERROR:
+			errno = conn->error;
+			break;
+		case WAIT_FAILURE:
+		default:
+			errno = ENOENT;
+			break;
+	}
+	conn->wait = WAIT_IDLE;
+	conn->mutex->unlock(conn->mutex);
+
+	conn->stream->on_read(conn->stream, on_read, conn);
+
+	if (message)
+	{
+		INIT(res,
+			.message = message,
+			.enumerator = message->create_enumerator(message),
+			.strings = linked_list_create(),
+		);
+		return res;
+	}
+	return NULL;
+}
+
+void vici_free_req(vici_req_t *req)
+{
+	vici_message_t *message;
+
+	free(req->name);
+	message = req->b->finalize(req->b);
+	if (message)
+	{
+		message->destroy(message);
+	}
+	free(req);
+}
+
+int vici_dump(vici_res_t *res, char *label, bool pretty, FILE *out)
+{
+	if (res->message->dump(res->message, label, pretty, out))
+	{
+		return 0;
+	}
+	errno = EBADMSG;
+	return 1;
+}
+
+vici_parse_t vici_parse(vici_res_t *res)
+{
+	if (!res->enumerator->enumerate(res->enumerator,
+									&res->type, &res->name, &res->value))
+	{
+		return VICI_PARSE_ERROR;
+	}
+	switch (res->type)
+	{
+		case VICI_END:
+			return VICI_PARSE_END;
+		case VICI_SECTION_START:
+			return VICI_PARSE_BEGIN_SECTION;
+		case VICI_SECTION_END:
+			return VICI_PARSE_END_SECTION;
+		case VICI_LIST_START:
+			return VICI_PARSE_BEGIN_LIST;
+		case VICI_LIST_ITEM:
+			return VICI_PARSE_LIST_ITEM;
+		case VICI_LIST_END:
+			return VICI_PARSE_END_LIST;
+		case VICI_KEY_VALUE:
+			return VICI_PARSE_KEY_VALUE;
+		default:
+			return VICI_PARSE_ERROR;
+	}
+}
+
+char* vici_parse_name(vici_res_t *res)
+{
+	char *name;
+
+	switch (res->type)
+	{
+		case VICI_SECTION_START:
+		case VICI_LIST_START:
+		case VICI_KEY_VALUE:
+			name = strdup(res->name);
+			res->strings->insert_last(res->strings, name);
+			return name;
+		default:
+			errno = EINVAL;
+			return NULL;
+	}
+}
+
+int vici_parse_name_eq(vici_res_t *res, char *name)
+{
+	switch (res->type)
+	{
+		case VICI_SECTION_START:
+		case VICI_LIST_START:
+		case VICI_KEY_VALUE:
+			return streq(name, res->name) ? 1 : 0;
+		default:
+			return 0;
+	}
+}
+
+void* vici_parse_value(vici_res_t *res, int *len)
+{
+	switch (res->type)
+	{
+		case VICI_LIST_ITEM:
+		case VICI_KEY_VALUE:
+			*len = res->value.len;
+			return res->value.ptr;
+		default:
+			*len = 0;
+			errno = EINVAL;
+			return NULL;
+	}
+}
+
+char* vici_parse_value_str(vici_res_t *res)
+{
+	char *val;
+
+	switch (res->type)
+	{
+		case VICI_LIST_ITEM:
+		case VICI_KEY_VALUE:
+			if (!chunk_printable(res->value, NULL, 0))
+			{
+				errno = EBADMSG;
+				return NULL;
+			}
+			val = strndup(res->value.ptr, res->value.len);
+			res->strings->insert_last(res->strings, val);
+			return val;
+		default:
+			errno = EINVAL;
+			return NULL;
+	}
+}
+
+int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
+				  vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
+				  void *user)
+{
+	char *name, *list = NULL;
+	void *value;
+	int base, len, ret;
+
+	base = res->level;
+
+	while (TRUE)
+	{
+		switch (vici_parse(res))
+		{
+			case VICI_PARSE_KEY_VALUE:
+				if (res->level == base)
+				{
+					if (kv)
+					{
+						name = vici_parse_name(res);
+						value = vici_parse_value(res, &len);
+						if (name && value)
+						{
+							ret = kv(user, res, name, value, len);
+							if (ret)
+							{
+								return ret;
+							}
+						}
+					}
+				}
+				break;
+			case VICI_PARSE_BEGIN_SECTION:
+				if (res->level++ == base)
+				{
+					if (section)
+					{
+						name = vici_parse_name(res);
+						if (name)
+						{
+							ret = section(user, res, name);
+							if (ret)
+							{
+								return ret;
+							}
+						}
+					}
+				}
+				break;
+			case VICI_PARSE_END_SECTION:
+				if (res->level-- == base)
+				{
+					return 0;
+				}
+				break;
+			case VICI_PARSE_END:
+				res->level = 0;
+				return 0;
+			case VICI_PARSE_BEGIN_LIST:
+				if (res->level == base)
+				{
+					list = vici_parse_name(res);
+				}
+				break;
+			case VICI_PARSE_LIST_ITEM:
+				if (list && li)
+				{
+					value = vici_parse_value(res, &len);
+					if (value)
+					{
+						ret = li(user, res, list, value, len);
+						if (ret)
+						{
+							return ret;
+						}
+					}
+				}
+				break;
+			case VICI_PARSE_END_LIST:
+				if (res->level == base)
+				{
+					list = NULL;
+				}
+				break;
+			case VICI_PARSE_ERROR:
+				res->level = 0;
+				errno = EBADMSG;
+				return 1;
+		}
+	}
+}
+
+void* vici_find(vici_res_t *res, int *len, char *fmt, ...)
+{
+	va_list args;
+	chunk_t value;
+
+	va_start(args, fmt);
+	value = res->message->vget_value(res->message, chunk_empty, fmt, args);
+	va_end(args);
+
+	*len = value.len;
+	return value.ptr;
+}
+
+char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...)
+{
+	va_list args;
+	char *str;
+
+	va_start(args, fmt);
+	str = res->message->vget_str(res->message, def, fmt, args);
+	va_end(args);
+
+	return str;
+}
+
+int vici_find_int(vici_res_t *res, int def, char *fmt, ...)
+{
+	va_list args;
+	int val;
+
+	va_start(args, fmt);
+	val = res->message->vget_int(res->message, def, fmt, args);
+	va_end(args);
+
+	return val;
+}
+
+void vici_free_res(vici_res_t *res)
+{
+	res->strings->destroy_function(res->strings, free);
+	res->message->destroy(res->message);
+	res->enumerator->destroy(res->enumerator);
+	free(res);
+}
+
+int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user)
+{
+	event_t *event;
+	u_int32_t len;
+	u_int8_t namelen, op;
+	int ret = 1;
+
+	op = cb ? VICI_EVENT_REGISTER : VICI_EVENT_UNREGISTER;
+	namelen = strlen(name);
+	len = htonl(sizeof(op) + sizeof(namelen) + namelen);
+	if (!conn->stream->write_all(conn->stream, &len, sizeof(len)) ||
+		!conn->stream->write_all(conn->stream, &op, sizeof(op)) ||
+		!conn->stream->write_all(conn->stream, &namelen, sizeof(namelen)) ||
+		!conn->stream->write_all(conn->stream, name, namelen))
+	{
+		return 1;
+	}
+
+	conn->mutex->lock(conn->mutex);
+	while (conn->wait == WAIT_IDLE)
+	{
+		conn->cond->wait(conn->cond, conn->mutex);
+	}
+	switch (conn->wait)
+	{
+		case WAIT_SUCCESS:
+			ret = 0;
+			break;
+		case WAIT_READ_ERROR:
+			errno = conn->error;
+			break;
+		case WAIT_FAILURE:
+		default:
+			errno = ENOENT;
+			break;
+	}
+	conn->wait = WAIT_IDLE;
+	conn->mutex->unlock(conn->mutex);
+
+	conn->stream->on_read(conn->stream, on_read, conn);
+
+	if (ret == 0)
+	{
+		conn->mutex->lock(conn->mutex);
+		if (cb)
+		{
+			INIT(event,
+				.name = strdup(name),
+				.cb = cb,
+				.user = user,
+			);
+			event = conn->events->put(conn->events, event->name, event);
+		}
+		else
+		{
+			event = conn->events->remove(conn->events, name);
+		}
+		conn->mutex->unlock(conn->mutex);
+
+		if (event)
+		{
+			free(event->name);
+			free(event);
+		}
+	}
+	return ret;
+}
+
+void vici_init()
+{
+	library_init(NULL, "vici");
+	if (lib->processor->get_total_threads(lib->processor) < 4)
+	{
+		lib->processor->set_threads(lib->processor, 4);
+	}
+}
+
+void vici_deinit()
+{
+	library_deinit();
+}
diff --git a/src/libcharon/plugins/vici/libvici.h b/src/libcharon/plugins/vici/libvici.h
new file mode 100644
index 0000000..58595d8
--- /dev/null
+++ b/src/libcharon/plugins/vici/libvici.h
@@ -0,0 +1,459 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup libvici libvici
+ * @{ @ingroup vici
+ *
+ * libvici is a low-level client library for the "Versatile IKE Control
+ * Interface" protocol. While it uses libstrongswan and its thread-pool for
+ * asynchronous message delivery, this interface does not directly depend on
+ * libstrongswan interfaces and should be stable.
+ *
+ * This interface provides the following basic functions:
+ *
+ * - vici_init()/vici_deinit(): Library initialization functions
+ * - vici_connect(): Connect to a vici service
+ * - vici_disconnect(): Disconnect from a vici service
+ *
+ * Library initialization implicitly initializes libstrongswan and a small
+ * thread pool.
+ *
+ * Connecting requires an uri, which is currently either a UNIX socket path
+ * prefixed with unix://, or a hostname:port touple prefixed with tcp://.
+ * Passing NULL takes the system default socket path.
+ *
+ * After the connection has been established, request messages can be sent.
+ * Only a single thread may operate on a single connection instance
+ * simultaneously. To construct request messages, use the following functions:
+ *
+ * - vici_add_key_value() / vici_add_key_valuef(): Add key/value pairs
+ * - vici_begin(): Start constructing a new request message
+ * - vici_begin_section(): Open a new section to add contents to
+ * - vici_end_section(): Close a previously opened session
+ * - vici_begin_list(): Open a new list to add list items to
+ * - vici_end_list(): Close a previously opened list
+ * - vici_add_list_item() / vici_add_list_itemf(): Add list item
+ *
+ * Once the request message is complete, it can be sent or cancelled with:
+ *
+ * - vici_submit()
+ * - vici_free_req()
+ *
+ * If submitting a message is successful, a response message is returned. It
+ * can be processed using the following functions:
+ *
+ * - vici_parse(): Parse content type
+ * - vici_parse_name(): Parse name if content type provides one
+ * - vici_parse_name_eq(): Parse name and check if matches string
+ * - vici_parse_value() / vici_parse_value_str(): Parse value for content type
+ * - vici_dump(): Dump a full response to a FILE stream
+ * - vici_free_res(): Free response after use
+ *
+ * Usually vici_parse() is called in a loop, and depending on the returned
+ * type the name and value can be inspected.
+ *
+ * To register or unregister for asynchronous event messages vici_register() is
+ * used. The registered callback gets invoked by an asynchronous thread. To
+ * parse the event message, the vici_parse*() functions can be used.
+ */
+
+#ifndef LIBVICI_H_
+#define LIBVICI_H_
+
+#include <stdio.h>
+
+#include <utils/utils.h>
+
+/**
+ * Opaque vici connection contex.
+ */
+typedef struct vici_conn_t vici_conn_t;
+
+/**
+ * Opaque vici request message.
+ */
+typedef struct vici_req_t vici_req_t;
+
+/**
+ * Opaque vici response/event message.
+ */
+typedef struct vici_res_t vici_res_t;
+
+/**
+ * Vici parse result, as returned by vici_parse().
+ */
+typedef enum {
+	/** encountered a section start, has a name */
+	VICI_PARSE_BEGIN_SECTION,
+	/** encountered a section end */
+	VICI_PARSE_END_SECTION,
+	/** encountered a list start, has a name */
+	VICI_PARSE_BEGIN_LIST,
+	/** encountered a list element, has a value */
+	VICI_PARSE_LIST_ITEM,
+	/** encountered a list end */
+	VICI_PARSE_END_LIST,
+	/** encountered a key/value pair, has a name and a value */
+	VICI_PARSE_KEY_VALUE,
+	/** encountered valid end of message */
+	VICI_PARSE_END,
+	/** parse error */
+	VICI_PARSE_ERROR,
+} vici_parse_t;
+
+/**
+ * Callback function invoked for received event messages.
+ *
+ * It is not allowed to call vici_submit() from this callback.
+ *
+ * @param user		user data, as passed to vici_connect
+ * @param name		name of received event
+ * @param msg		associated event message, destroyed by libvici
+ */
+typedef void (*vici_event_cb_t)(void *user, char *name, vici_res_t *msg);
+
+/**
+ * Callback function for key/value and list items, invoked by vici_parse_cb().
+ *
+ * @param user		user data, as passed to vici_parse_cb()
+ * @param res		message currently parsing
+ * @param name		name of key or list
+ * @param value		value buffer
+ * @param len		length of value buffer
+ * @return			0 if parsed successfully
+ */
+typedef int	(*vici_parse_value_cb_t)(void *user, vici_res_t *res, char *name,
+									 void *value, int len);
+
+/**
+ * Callback function for sections, invoked by vici_parse_cb().
+ *
+ * @param user		user data, as passed to vici_parse_cb()
+ * @param res		message currently parsing
+ * @param name		name of the section
+ * @return			0 if parsed successfully
+ */
+typedef int (*vici_parse_section_cb_t)(void *user, vici_res_t *res, char *name);
+
+/**
+ * Open a new vici connection.
+ *
+ * On error, NULL is returned and errno is set appropriately.
+ *
+ * @param uri		URI to connect to, NULL to use system default
+ * @return			opaque vici connection context, NULL on error
+ */
+vici_conn_t* vici_connect(char *uri);
+
+/**
+ * Close a vici connection.
+ *
+ * @param conn		connection context
+ */
+void vici_disconnect(vici_conn_t *conn);
+
+/**
+ * Begin a new vici message request.
+ *
+ * This function always succeeds.
+ *
+ * @param name		name of request command
+ * @return			request message, to add contents
+ */
+vici_req_t* vici_begin(char *name);
+
+/**
+ * Begin a new section in a vici request message.
+ *
+ * @param req		request message to create a new section in
+ * @param name		name of section to create
+ */
+void vici_begin_section(vici_req_t *req, char *name);
+
+/**
+ * End a previously opened section.
+ *
+ * @param req		request message to close an open section in
+ */
+void vici_end_section(vici_req_t *req);
+
+/**
+ * Add a key/value pair, using an as-is blob as value.
+ *
+ * @param req		request message to add key/value pair to
+ * @param key		key name of key/value pair
+ * @param buf		pointer to blob to add as value
+ * @param len		length of value blob to add
+ */
+void vici_add_key_value(vici_req_t *req, char *key, void *buf, int len);
+
+/**
+ * Add a key/value pair, setting value from a printf() format string.
+ *
+ * @param req		request message to add key/value pair to
+ * @param key		key name of key/value pair
+ * @param fmt		format string for value
+ * @param ...		arguments to format string
+ */
+void vici_add_key_valuef(vici_req_t *req, char *key, char *fmt, ...);
+
+/**
+ * Begin a list in a request message.
+ *
+ * After starting a list, only list items can be added until the list gets
+ * closed by vici_end_list().
+ *
+ * @param req		request message to begin list in
+ * @param name		name of list to begin
+ */
+void vici_begin_list(vici_req_t *req, char *name);
+
+/**
+ * Add a list item to a currently open list, using an as-is blob.
+ *
+ * @param req		request message to add list item to
+ * @param buf		pointer to blob to add as value
+ * @param len		length of value blob to add
+ */
+void vici_add_list_item(vici_req_t *req, void *buf, int len);
+
+/**
+ * Add a list item to a currently open list, using a printf() format string.
+ *
+ * @param req		request message to add list item to
+ * @param fmt		format string to create value from
+ * @param ...		arguments to format string
+ */
+void vici_add_list_itemf(vici_req_t *req, char *fmt, ...);
+
+/**
+ * End a previously opened list in a request message.
+ *
+ * @param req		request message to end list in
+ */
+void vici_end_list(vici_req_t *req);
+
+/**
+ * Submit a request message, and wait for response.
+ *
+ * The request messages gets cleaned up by this call and gets invalid.
+ * On error, NULL is returned an errno is set to:
+ * - EINVAL if the request is invalid/incomplete
+ * - ENOENT if the command is unknown
+ * - EBADMSG if the response is invalid
+ * - Any other IO related errno
+ *
+ * @param req		request message to send
+ * @param conn		connection context to send message over
+ * @return			response message, NULL on error
+ */
+vici_res_t* vici_submit(vici_req_t *req, vici_conn_t *conn);
+
+/**
+ * Cancel a request message started.
+ *
+ * If a request created by vici_begin() does not get submitted using
+ * vici_submit(), it has to get freed using this call.
+ *
+ * @param req		request message to clean up
+ */
+void vici_free_req(vici_req_t *req);
+
+/**
+ * Dump a message text representation to a FILE stream.
+ *
+ * On error, errno is set to:
+ * - EBADMSG if the message is invalid
+ *
+ * @param res		response message to dump
+ * @param label		a label to print for this message
+ * @param pretty	use pretty print with indentation
+ * @param out		FILE to dump to
+ * @return			0 if dumped complete message, 1 on error
+ */
+int vici_dump(vici_res_t *res, char *label, bool pretty, FILE *out);
+
+/**
+ * Parse next element from a vici response message.
+ *
+ * @param res		response message to parse
+ * @return			parse result
+ */
+vici_parse_t vici_parse(vici_res_t *res);
+
+/**
+ * Parse name tag / key of a previously parsed element.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE,
+ * VICI_PARSE_BEGIN_SECTION or VICI_PARSE_BEGIN_LIST.
+ *
+ * The string is valid until vici_free_res() is called.
+ *
+ * On error, errno is set to:
+ *- EINVAL if not in valid parser state
+ *
+ * @param res		response message to parse
+ * @return			name tag / key, NULL on error
+ */
+char* vici_parse_name(vici_res_t *res);
+
+/**
+ * Compare name tag / key of a previusly parsed element.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE,
+ * VICI_PARSE_BEGIN_SECTION or VICI_PARSE_BEGIN_LIST.
+ *
+ * @param res		response message to parse
+ * @param name		string to compare
+ * @return			1 if name equals, 0 if not
+ */
+int vici_parse_name_eq(vici_res_t *res, char *name);
+
+/**
+ * Parse value of a previously parsed element, as a blob.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE or
+ * VICI_PARSE_LIST_ITEM.
+ *
+ * The string is valid until vici_free_res() is called.
+ *
+ * On error, errno is set to:
+ * - EINVAL if not in valid parser state
+ *
+ * @param res		response message to parse
+ * @param len		pointer receiving value length
+ * @return			pointer to value, NULL on error
+ */
+void* vici_parse_value(vici_res_t *res, int *len);
+
+/**
+ * Parse value of a previously parsed element, as a string.
+ *
+ * This call is valid only after vici_parse() returned VICI_PARSE_KEY_VALUE or
+ * VICI_PARSE_LIST_ITEM.
+ *
+ * This call is successful only if the value contains no non-printable
+ * characters. The string is valid until vici_free_res() is called.
+ *
+ * On error, errno is set to:
+ * - EBADMSG if value is not a printable string
+ * - EINVAL if not in valid parser state
+ *
+ * @param res		response message to parse
+ * @return			value as string, NULL on error
+ */
+char* vici_parse_value_str(vici_res_t *res);
+
+/**
+ * Parse a complete message with callbacks.
+ *
+ * Any of the callbacks may be NULL to skip this kind of item. Callbacks are
+ * invoked for the current section level only. To descent into sections, call
+ * vici_parse_cb() from within a section callback.
+ *
+ * On error, errno is set to:
+ * - EBADMSG if message encoding invalid
+ * - Any other errno set by the invoked callbacks
+ *
+ * @param res		message to parse
+ * @param section	callback invoked for each section
+ * @param kv		callback invoked for key/value pairs
+ * @param li		callback invoked for list items
+ * @param user		user data to pass to callbacks
+ * @return			0 if parsing successful
+ */
+int vici_parse_cb(vici_res_t *res, vici_parse_section_cb_t section,
+				  vici_parse_value_cb_t kv, vici_parse_value_cb_t li,
+				  void *user);
+
+/*
+ * Find a blob value in a message for a given key.
+ *
+ * Sections can be selected by prefixing them separated by dots.
+ *
+ * @param res		response message to parse
+ * @param len		length of returned object
+ * @param fmt		printf format string of key and sections
+ * @param ...		arguments to format string
+ * @return			blob value, having *len bytes, NULL if not found
+ */
+void *vici_find(vici_res_t *res, int *len, char *fmt, ...);
+
+/**
+ * Find a string value in a message for a given key.
+ *
+ * Sections can be selected by prefixing them separated by dots.
+ *
+ * @param res		response message to parse
+ * @param def		default value, if key not found
+ * @param fmt		printf format string of key and sections
+ * @param ...		arguments to format string
+ * @return			string, def if not found
+ */
+char* vici_find_str(vici_res_t *res, char *def, char *fmt, ...);
+
+/**
+ * Find an integer value in a message for a given key.
+ *
+ * Sections can be selected by prefixing them separated by dots.
+ *
+ * @param res		response message to parse
+ * @param def		default value, if key not found
+ * @param fmt		printf format string of key and sections
+ * @param ...		arguments to format string
+ * @return			integer value, def if not found
+ */
+int vici_find_int(vici_res_t *res, int def, char *fmt, ...);
+
+/**
+ * Clean up a received response message.
+ *
+ * Event messages get cleaned up by the library, it is not allowed to call
+ * vici_free_res() from within a vici_event_cb_t.
+ *
+ * @param res		response message to free
+ */
+void vici_free_res(vici_res_t *res);
+
+/**
+ * (Un-)Register for events of a given kind.
+ *
+ * Events callbacks get invoked by a different thread from the libstrongswan
+ * thread pool.
+ * On failure, errno is set to:
+ * - ENOENT if the event name is unknown
+ * - EBADMSG if the response is invalid
+ * - Any other IO related errno
+ *
+ * @param conn		connection context
+ * @param name		name of event messages to register to
+ * @param cb		callback function to register, NULL to unregister
+ * @param user		user data passed to callback invocations
+ * @return			0 if registered successfully
+ */
+int vici_register(vici_conn_t *conn, char *name, vici_event_cb_t cb, void *user);
+
+/**
+ * Initialize libvici before first time use.
+ */
+void vici_init();
+
+/**
+ * Deinitialize libvici after use.
+ */
+void vici_deinit();
+
+#endif /** LIBVICI_H_ @}*/
diff --git a/src/libcharon/plugins/vici/suites/test_event.c b/src/libcharon/plugins/vici/suites/test_event.c
new file mode 100644
index 0000000..b923ad3
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_event.c
@@ -0,0 +1,224 @@
+/*
+ * 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_suite.h>
+
+#include "../vici_dispatcher.h"
+#include "../libvici.h"
+
+#include <unistd.h>
+
+#ifdef WIN32
+# define URI "tcp://127.0.0.1:6543"
+#else /* !WIN32 */
+# define URI "unix:///tmp/strongswan-vici-event-test"
+#endif /* !WIN32 */
+
+static void event_cb(void *user, char *name, vici_res_t *ev)
+{
+	int *count = (int*)user;
+
+	ck_assert_str_eq(name, "test");
+	ck_assert(vici_parse(ev) == VICI_PARSE_KEY_VALUE);
+	ck_assert_str_eq(vici_parse_name(ev), "key1");
+	ck_assert_str_eq(vici_parse_value_str(ev), "value1");
+	ck_assert(vici_parse(ev) == VICI_PARSE_END);
+
+	(*count)++;
+}
+
+START_TEST(test_event)
+{
+	vici_dispatcher_t *dispatcher;
+	vici_conn_t *conn;
+	int count = 0;
+
+	lib->processor->set_threads(lib->processor, 8);
+
+	dispatcher = vici_dispatcher_create(URI);
+	ck_assert(dispatcher);
+
+	dispatcher->manage_event(dispatcher, "test", TRUE);
+
+	vici_init();
+	conn = vici_connect(URI);
+	ck_assert(conn);
+
+	ck_assert(vici_register(conn, "test", event_cb, &count) == 0);
+	ck_assert(vici_register(conn, "nonexistent", event_cb, &count) != 0);
+
+	dispatcher->raise_event(dispatcher, "test", 0, vici_message_create_from_args(
+		 VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+		VICI_END));
+
+	while (count == 0)
+	{
+		usleep(1000);
+	}
+
+	vici_disconnect(conn);
+
+	dispatcher->manage_event(dispatcher, "test", FALSE);
+
+	lib->processor->cancel(lib->processor);
+	dispatcher->destroy(dispatcher);
+
+	vici_deinit();
+}
+END_TEST
+
+#define EVENT_COUNT 500
+
+CALLBACK(raise_cb,  vici_message_t*,
+	vici_dispatcher_t *dispatcher, char *name, u_int id, vici_message_t *req)
+{
+	u_int i;
+
+	for (i = 0; i < EVENT_COUNT; i++)
+	{
+		dispatcher->raise_event(dispatcher, "event", id,
+			vici_message_create_from_args(
+				 VICI_KEY_VALUE, "counter", chunk_from_thing(i),
+				VICI_END));
+	}
+	return vici_message_create_from_args(VICI_END);
+}
+
+CALLBACK(raise_event_cb, void,
+	int *count, char *name, vici_res_t *ev)
+{
+	u_int *value, len;
+
+	ck_assert_str_eq(name, "event");
+	ck_assert(vici_parse(ev) == VICI_PARSE_KEY_VALUE);
+	ck_assert_str_eq(vici_parse_name(ev), "counter");
+	value = vici_parse_value(ev, &len);
+	ck_assert_int_eq(len, sizeof(*value));
+	ck_assert(vici_parse(ev) == VICI_PARSE_END);
+
+	ck_assert_int_eq(*count, *value);
+	(*count)++;
+}
+
+START_TEST(test_raise_events)
+{
+	vici_dispatcher_t *dispatcher;
+	vici_res_t *res;
+	vici_conn_t *conn;
+	int count = 0;
+
+	lib->processor->set_threads(lib->processor, 8);
+
+	dispatcher = vici_dispatcher_create(URI);
+	ck_assert(dispatcher);
+
+	dispatcher->manage_event(dispatcher, "event", TRUE);
+	dispatcher->manage_command(dispatcher, "raise", raise_cb, dispatcher);
+
+	vici_init();
+	conn = vici_connect(URI);
+	ck_assert(conn);
+
+	ck_assert(vici_register(conn, "event", raise_event_cb, &count) == 0);
+
+	res = vici_submit(vici_begin("raise"), conn);
+
+	ck_assert_int_eq(count, EVENT_COUNT);
+	ck_assert(res);
+	vici_free_res(res);
+
+	vici_disconnect(conn);
+
+	dispatcher->manage_event(dispatcher, "event", FALSE);
+	dispatcher->manage_command(dispatcher, "raise", NULL, NULL);
+
+	lib->processor->cancel(lib->processor);
+	dispatcher->destroy(dispatcher);
+
+	vici_deinit();
+}
+END_TEST
+
+START_TEST(test_stress)
+{
+	vici_dispatcher_t *dispatcher;
+	vici_conn_t *conn;
+	int count = 0, i, total = 50;
+
+	lib->processor->set_threads(lib->processor, 8);
+
+	dispatcher = vici_dispatcher_create(URI);
+	ck_assert(dispatcher);
+
+	dispatcher->manage_event(dispatcher, "test", TRUE);
+	dispatcher->manage_event(dispatcher, "dummy", TRUE);
+
+	vici_init();
+	conn = vici_connect(URI);
+	ck_assert(conn);
+
+	vici_register(conn, "test", event_cb, &count);
+
+	for (i = 0; i < total; i++)
+	{
+		/* do some event re/deregistration in between */
+		ck_assert(vici_register(conn, "dummy", event_cb, NULL) == 0);
+
+		dispatcher->raise_event(dispatcher, "test", 0,
+			vici_message_create_from_args(
+				 VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+				VICI_END));
+
+		ck_assert(vici_register(conn, "dummy", NULL, NULL) == 0);
+	}
+
+	while (count < total)
+	{
+		usleep(1000);
+	}
+
+	vici_disconnect(conn);
+
+	dispatcher->manage_event(dispatcher, "test", FALSE);
+	dispatcher->manage_event(dispatcher, "dummy", FALSE);
+
+	lib->processor->cancel(lib->processor);
+	dispatcher->destroy(dispatcher);
+
+	vici_deinit();
+}
+END_TEST
+
+Suite *event_suite_create()
+{
+	Suite *s;
+	TCase *tc;
+
+	s = suite_create("vici events");
+
+	tc = tcase_create("single");
+	tcase_add_test(tc, test_event);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("raise events");
+	tcase_add_test(tc, test_raise_events);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("stress");
+	tcase_add_test(tc, test_stress);
+	suite_add_tcase(s, tc);
+
+	return s;
+}
diff --git a/src/libcharon/plugins/vici/suites/test_message.c b/src/libcharon/plugins/vici/suites/test_message.c
new file mode 100644
index 0000000..2931173
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_message.c
@@ -0,0 +1,407 @@
+/*
+ * 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_suite.h>
+
+#include "../vici_message.h"
+#include "../vici_builder.h"
+
+#include <unistd.h>
+
+static char blob[] = {
+	0xd3,0xe5,0xee,0x37,0x7b,0x96,0x2f,0x3e,0x5f,0x3e,0x91,0xea,0x38,0x44,0xba,0x6c,
+	0x75,0xc8,0x42,0x32,0xaf,0x7a,0x66,0x43,0x33,0x92,0xd2,0xef,0x7d,0x91,0x7b,0x59,
+	0x9f,0x9f,0xd1,0x44,0xb6,0x1e,0x8c,0xd1,0xc5,0xa0,0xd9,0xe4,0xf2,0x31,0xfd,0x7b,
+	0x5b,0x56,0xa7,0xfe,0x63,0x0d,0xcb,0x31,0x74,0xd8,0xd6,0x4a,0x42,0x3a,0x88,0xf3,
+	0x79,0xf9,0x41,0xa6,0xc0,0x64,0x53,0x31,0x42,0xe2,0xd4,0x4a,0x22,0x5f,0x3f,0x99,
+	0xe0,0x1a,0xcb,0x93,0x26,0xd0,0xec,0xac,0x90,0x97,0x0a,0x5f,0x69,0x86,0xf1,0xda,
+	0xfc,0xa7,0xac,0xd0,0xd8,0x81,0xcf,0x7d,0x47,0x22,0xbe,0xbf,0x00,0x9b,0x6b,0x86,
+	0x92,0x89,0xbe,0x7f,0x74,0x13,0x53,0xf1,0x4c,0x2b,0xc9,0xe1,0x39,0xd6,0xfc,0x50,
+	0x3f,0x00,0xfb,0x76,0x42,0xa6,0xa4,0x70,0xfc,0x93,0x17,0x4a,0x35,0xce,0x5e,0x78,
+	0x41,0x88,0x24,0x50,0x78,0xf2,0x38,0x08,0xff,0x40,0xef,0x61,0xbb,0xbf,0x16,0xff,
+	0x0b,0xf6,0x33,0x21,0xcb,0x48,0xbd,0x7d,0xd1,0x73,0xfa,0x6d,0xd6,0xab,0xde,0x69,
+	0x63,0x17,0xdb,0x52,0xe2,0x75,0x4b,0xb7,0x1e,0xf0,0x8a,0x55,0x4f,0x70,0x8d,0x18,
+	0xe5,0x38,0x6a,0x9f,0xb8,0x06,0xb5,0x91,0x90,0x2b,0xc5,0x67,0xa9,0x12,0xe5,0xf3,
+	0x48,0x2f,0x80,0x03,0xa1,0xa0,0xfc,0x43,0xe9,0x0f,0x83,0x2b,0xbc,0x7c,0xa8,0x3b,
+	0x6c,0xc1,0xc8,0x72,0x5f,0x87,0x63,0x77,0x93,0x9b,0xe2,0xd7,0x4e,0xe6,0x65,0xa1,
+	0x69,0x00,0xda,0xf8,0xb4,0x61,0xee,0xb7,0x20,0xe7,0x2a,0x35,0x23,0xf0,0x37,0x4b,
+	0x67,0xcf,0x8d,0x85,0x72,0x22,0x6d,0x7a,0xb2,0x96,0xff,0x49,0xf4,0x94,0x3e,0x7e,
+	0x87,0x26,0x5d,0x34,0x05,0x26,0x60,0x9b,0x89,0xfe,0xf9,0x91,0xd3,0x03,0xe7,0x8a,
+	0x03,0xf6,0x4e,0xbf,0x68,0x13,0xc6,0xf2,0x7b,0x9c,0xe6,0x36,0x1b,0xe2,0x22,0x44,
+	0xb1,0x19,0x34,0x5f,0xe8,0x44,0x48,0x3a,0x19,0xe4,0xbd,0xb0,0x4e,0xb5,0x2c,0x40,
+	0x55,0x39,0xe6,0x4c,0xd5,0x68,0x34,0x72,0x6b,0x6d,0x88,0xce,0x7e,0x77,0x95,0x17,
+	0x2e,0x68,0x3f,0x0e,0x9d,0x70,0x9a,0x22,0xfa,0x19,0xcc,0x15,0x9d,0xba,0xaa,0xec,
+	0xb1,0x67,0x19,0x51,0xce,0x60,0x9a,0x38,0xf8,0xa7,0x4e,0xe3,0x25,0x47,0x1e,0x1d,
+	0x30,0x76,0x91,0x8f,0x4d,0x13,0x59,0x06,0x2f,0x01,0x10,0x95,0xdb,0x08,0x7c,0x46,
+	0xed,0x47,0xa1,0x19,0x4c,0x46,0xd1,0x3a,0x3f,0x88,0x7a,0x63,0xae,0x29,0x13,0x42,
+	0xe9,0x17,0xe8,0xa9,0x95,0xfc,0xd1,0xea,0xfa,0x59,0x90,0xfe,0xb7,0xbb,0x7f,0x61,
+	0x1b,0xcb,0x3d,0x12,0x99,0x96,0x3e,0x23,0x23,0xec,0x3a,0x4d,0x86,0x86,0x74,0xef,
+	0x38,0xa6,0xdc,0x3a,0x83,0x85,0xf8,0xb8,0xad,0x5b,0x33,0x94,0x4d,0x0e,0x68,0xbc,
+	0xf2,0xc7,0x6f,0x84,0x18,0x1e,0x5a,0x66,0x1f,0x6c,0x98,0x33,0xda,0xde,0x9e,0xda,
+	0x82,0xd0,0x56,0x44,0x47,0x08,0x0c,0x07,0x81,0x9d,0x8b,0x64,0x16,0x73,0x9d,0x80,
+	0x54,0x9c,0x4c,0x42,0xde,0x27,0x4e,0x97,0xb2,0xcf,0x48,0xaf,0x7e,0x85,0xc1,0xcd,
+	0x6a,0x4d,0x04,0x40,0x89,0xa3,0x9d,0x4e,0x89,0x56,0x60,0x31,0x1f,0x3f,0x49,0x16,
+};
+
+typedef struct {
+	vici_type_t type;
+	char *name;
+	chunk_t data;
+} endecode_test_t;
+
+static endecode_test_t endecode_test_simple[] = {
+	{ VICI_SECTION_START,			"section1", {}							},
+	{  VICI_KEY_VALUE,				"key1",		{ "value1", 6 }				},
+	{  VICI_KEY_VALUE,				"key2",		{ "value2", 6 }				},
+	{ VICI_SECTION_END,				NULL,		{}							},
+	{ VICI_END,						NULL,		{}							},
+};
+
+static endecode_test_t endecode_test_nested[] = {
+	{ VICI_SECTION_START,			"section1", {}							},
+	{  VICI_SECTION_START,			"section2", {}							},
+	{   VICI_SECTION_START,			"section3", {}							},
+	{    VICI_KEY_VALUE,			"key1",		{ "value1", 6 }				},
+	{    VICI_SECTION_START,		"section4", {}							},
+	{     VICI_KEY_VALUE,			"key2",		{ "value2", 6 }				},
+	{    VICI_SECTION_END,			NULL,		{}							},
+	{   VICI_SECTION_END,			NULL,		{}							},
+	{  VICI_SECTION_END,			NULL,		{}							},
+	{  VICI_KEY_VALUE,				"key3",		{ "value3", 6 }				},
+	{ VICI_SECTION_END,				NULL,		{}							},
+	{ VICI_END,						NULL,		{}							},
+};
+
+static endecode_test_t endecode_test_list[] = {
+	{ VICI_SECTION_START,			"section1", {}							},
+	{  VICI_LIST_START,				"list1",	{}							},
+	{   VICI_LIST_ITEM,				NULL,		{ "item1", 5 }				},
+	{   VICI_LIST_ITEM,				NULL,		{ "item2", 5 }				},
+	{  VICI_LIST_END,				NULL,		{}							},
+	{  VICI_KEY_VALUE,				"key1",		{ "value1", 6 }				},
+	{ VICI_SECTION_END,				NULL,		{}							},
+	{ VICI_END,						NULL,		{}							},
+};
+
+static endecode_test_t endecode_test_blobs[] = {
+	{ VICI_KEY_VALUE,				"key1",		{ blob, countof(blob) }		},
+	{ VICI_SECTION_START,			"section1", {}							},
+	{  VICI_LIST_START,				"list1",	{}							},
+	{   VICI_LIST_ITEM,				NULL,		{ blob, countof(blob) }		},
+	{   VICI_LIST_ITEM,				NULL,		{ blob, countof(blob) }		},
+	{  VICI_LIST_END,				NULL,		{}							},
+	{  VICI_KEY_VALUE,				"key2",		{ blob, countof(blob) }		},
+	{ VICI_SECTION_END,				NULL,		{}							},
+	{ VICI_END,						NULL,		{}							},
+};
+
+static endecode_test_t *endecode_tests[] = {
+	endecode_test_simple,
+	endecode_test_nested,
+	endecode_test_list,
+	endecode_test_blobs,
+};
+
+typedef struct {
+	enumerator_t public;
+	endecode_test_t *next;
+} endecode_enum_t;
+
+static bool endecode_enumerate(endecode_enum_t *this, vici_type_t *type,
+							   char **name, chunk_t *data)
+{
+	if (this->next)
+	{
+		*type = this->next->type;
+		*name = this->next->name;
+		*data = this->next->data;
+		if (this->next->type == VICI_END)
+		{
+			this->next = NULL;
+		}
+		else
+		{
+			this->next++;
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static enumerator_t *endecode_create_enumerator(endecode_test_t *test)
+{
+	endecode_enum_t *enumerator;
+
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)endecode_enumerate,
+			.destroy = (void*)free,
+		},
+		.next = test,
+	);
+
+	return &enumerator->public;
+}
+
+static void compare_vici(enumerator_t *parse, enumerator_t *tmpl)
+{
+	vici_type_t type, ttype;
+	char *name, *tname;
+	chunk_t data, tdata;;
+
+	while (TRUE)
+	{
+		ck_assert(parse->enumerate(parse, &type, &name, &data));
+		ck_assert(tmpl->enumerate(tmpl, &ttype, &tname, &tdata));
+		ck_assert_int_eq(type, ttype);
+		switch (type)
+		{
+			case VICI_END:
+				return;
+			case VICI_SECTION_START:
+			case VICI_LIST_START:
+				ck_assert(streq(name, tname));
+				break;
+			case VICI_LIST_ITEM:
+				ck_assert(chunk_equals(data, tdata));
+				break;
+			case VICI_KEY_VALUE:
+				ck_assert(streq(name, tname));
+				ck_assert(chunk_equals(data, tdata));
+				break;
+			case VICI_SECTION_END:
+			case VICI_LIST_END:
+				break;
+			default:
+				ck_assert(FALSE);
+				break;
+		}
+	}
+}
+
+START_TEST(test_endecode)
+{
+	enumerator_t *parse, *tmpl;
+	vici_message_t *m;
+	chunk_t data;
+
+	tmpl = endecode_create_enumerator(endecode_tests[_i]);
+	m = vici_message_create_from_enumerator(tmpl);
+	ck_assert(m);
+	data = chunk_clone(m->get_encoding(m));
+	tmpl = endecode_create_enumerator(endecode_tests[_i]);
+	parse = m->create_enumerator(m);
+	ck_assert(parse);
+	compare_vici(parse, tmpl);
+	tmpl->destroy(tmpl);
+	parse->destroy(parse);
+	m->destroy(m);
+
+	m = vici_message_create_from_data(data, TRUE);
+	ck_assert(m);
+	tmpl = endecode_create_enumerator(endecode_tests[_i]);
+	parse = m->create_enumerator(m);
+	ck_assert(parse);
+	compare_vici(parse, tmpl);
+	tmpl->destroy(tmpl);
+	parse->destroy(parse);
+	m->destroy(m);
+}
+END_TEST
+
+START_TEST(test_vararg)
+{
+	enumerator_t *parse, *tmpl;
+	vici_message_t *m;
+
+	m = vici_message_create_from_args(
+		VICI_SECTION_START, "section1",
+		 VICI_LIST_START, "list1",
+		  VICI_LIST_ITEM, chunk_from_str("item1"),
+		  VICI_LIST_ITEM, chunk_from_str("item2"),
+		 VICI_LIST_END,
+		 VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+		 VICI_SECTION_END,
+		VICI_END);
+	ck_assert(m);
+	tmpl = endecode_create_enumerator(endecode_test_list);
+	parse = m->create_enumerator(m);
+	ck_assert(parse);
+
+	compare_vici(parse, tmpl);
+
+	m->destroy(m);
+	tmpl->destroy(tmpl);
+	parse->destroy(parse);
+}
+END_TEST
+
+START_TEST(test_builder)
+{
+	enumerator_t *parse, *tmpl;
+	vici_message_t *m;
+	vici_builder_t *b;
+
+	b = vici_builder_create();
+	b->add(b, VICI_SECTION_START, "section1");
+	b->add(b,  VICI_LIST_START, "list1");
+	b->add(b,   VICI_LIST_ITEM, chunk_from_str("item1"));
+	b->add(b,   VICI_LIST_ITEM, chunk_from_str("item2"));
+	b->add(b,  VICI_LIST_END);
+	b->add(b,  VICI_KEY_VALUE, "key1", chunk_from_str("value1"));
+	b->add(b, VICI_SECTION_END);
+	m = b->finalize(b);
+	ck_assert(m);
+	tmpl = endecode_create_enumerator(endecode_test_list);
+	parse = m->create_enumerator(m);
+	ck_assert(parse);
+
+	compare_vici(parse, tmpl);
+
+	m->destroy(m);
+	tmpl->destroy(tmpl);
+	parse->destroy(parse);
+}
+END_TEST
+
+START_TEST(test_builder_fmt)
+{
+	enumerator_t *parse, *tmpl;
+	vici_message_t *m;
+	vici_builder_t *b;
+
+	b = vici_builder_create();
+	b->begin_section(b, "section1");
+	b->begin_list(b, "list1");
+	b->add_li(b, "item%u", 1);
+	b->add_li(b, "%s%u", "item", 2);
+	b->end_list(b);
+	b->add_kv(b, "key1", "value%u", 1);
+	b->end_section(b);
+	m = b->finalize(b);
+	ck_assert(m);
+	tmpl = endecode_create_enumerator(endecode_test_list);
+	parse = m->create_enumerator(m);
+	ck_assert(parse);
+
+	compare_vici(parse, tmpl);
+
+	m->destroy(m);
+	tmpl->destroy(tmpl);
+	parse->destroy(parse);
+}
+END_TEST
+
+static vici_message_t* build_getter_msg()
+{
+	return vici_message_create_from_args(
+			VICI_KEY_VALUE, "key1", chunk_from_str("1"),
+			VICI_SECTION_START, "section1",
+			 VICI_KEY_VALUE, "key2", chunk_from_str("0x12"),
+			 VICI_SECTION_START, "section2",
+			  VICI_KEY_VALUE, "key3", chunk_from_str("-1"),
+			 VICI_SECTION_END,
+			 VICI_KEY_VALUE, "key4", chunk_from_str("asdf"),
+			VICI_SECTION_END,
+			VICI_KEY_VALUE, "key5", chunk_from_str(""),
+			VICI_END);
+}
+
+START_TEST(test_get_str)
+{
+	vici_message_t *m;
+
+	m = build_getter_msg();
+
+	ck_assert_str_eq(m->get_str(m, "def", "key1"), "1");
+	ck_assert_str_eq(m->get_str(m, "def", "section1.key2"), "0x12");
+	ck_assert_str_eq(m->get_str(m, "def", "section%d.section2.key3", 1), "-1");
+	ck_assert_str_eq(m->get_str(m, "def", "section1.key4"), "asdf");
+	ck_assert_str_eq(m->get_str(m, "def", "key5"), "");
+	ck_assert_str_eq(m->get_str(m, "no", "nonexistent"), "no");
+	ck_assert_str_eq(m->get_str(m, "no", "n.o.n.e.x.i.s.t.e.n.t"), "no");
+
+	m->destroy(m);
+}
+END_TEST
+
+START_TEST(test_get_int)
+{
+	vici_message_t *m;
+
+	m = build_getter_msg();
+
+	ck_assert_int_eq(m->get_int(m, 2, "key1"), 1);
+	ck_assert_int_eq(m->get_int(m, 2, "section1.key2"), 0x12);
+	ck_assert_int_eq(m->get_int(m, 2, "section1.section2.key3"), -1);
+	ck_assert_int_eq(m->get_int(m, 2, "section1.key4"), 2);
+	ck_assert_int_eq(m->get_int(m, 2, "key5"), 0);
+	ck_assert_int_eq(m->get_int(m, 2, "nonexistent"), 2);
+	ck_assert_int_eq(m->get_int(m, 2, "n.o.n.e.x.i.s.t.e.n.t"), 2);
+
+	m->destroy(m);
+}
+END_TEST
+
+START_TEST(test_get_value)
+{
+	vici_message_t *m;
+	chunk_t d = chunk_from_chars('d','e','f');
+
+	m = build_getter_msg();
+
+	ck_assert_chunk_eq(m->get_value(m, d, "key1"), chunk_from_str("1"));
+	ck_assert_chunk_eq(m->get_value(m, d, "section1.key2"), chunk_from_str("0x12"));
+	ck_assert_chunk_eq(m->get_value(m, d, "section1.section2.key3"), chunk_from_str("-1"));
+	ck_assert_chunk_eq(m->get_value(m, d, "section1.key4"), chunk_from_str("asdf"));
+	ck_assert_chunk_eq(m->get_value(m, d, "key5"), chunk_empty);
+	ck_assert_chunk_eq(m->get_value(m, d, "nonexistent"), d);
+	ck_assert_chunk_eq(m->get_value(m, d, "n.o.n.e.x.i.s.t.e.n.t"), d);
+
+	m->destroy(m);
+}
+END_TEST
+
+Suite *message_suite_create()
+{
+	Suite *s;
+	TCase *tc;
+
+	s = suite_create("vici message");
+
+	tc = tcase_create("enumerator en/decode");
+	tcase_add_loop_test(tc, test_endecode, 0, countof(endecode_tests));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("vararg encode");
+	tcase_add_test(tc, test_vararg);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("builder encode");
+	tcase_add_test(tc, test_builder);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("builder format encode");
+	tcase_add_test(tc, test_builder_fmt);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("convenience getters");
+	tcase_add_test(tc, test_get_str);
+	tcase_add_test(tc, test_get_int);
+	tcase_add_test(tc, test_get_value);
+	suite_add_tcase(s, tc);
+
+	return s;
+}
diff --git a/src/libcharon/plugins/vici/suites/test_request.c b/src/libcharon/plugins/vici/suites/test_request.c
new file mode 100644
index 0000000..8eeb37b
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_request.c
@@ -0,0 +1,247 @@
+/*
+ * 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_suite.h>
+
+#include "../vici_dispatcher.h"
+#include "../libvici.h"
+
+#include <unistd.h>
+
+#ifdef WIN32
+# define URI "tcp://127.0.0.1:6543"
+#else /* !WIN32 */
+# define URI "unix:///tmp/strongswan-vici-request-test"
+#endif /* !WIN32 */
+
+static void encode_section(vici_req_t *req)
+{
+	vici_begin_section(req, "section1");
+	vici_add_key_valuef(req, "key1", "value%u", 1);
+	vici_add_key_value(req, "key2", "value2", strlen("value2"));
+	vici_end_section(req);
+}
+
+static void decode_section(vici_res_t *res)
+{
+	char *str;
+	int len;
+
+	ck_assert(vici_parse(res) == VICI_PARSE_BEGIN_SECTION);
+	ck_assert_str_eq(vici_parse_name(res), "section1");
+	ck_assert(vici_parse(res) == VICI_PARSE_KEY_VALUE);
+	ck_assert_str_eq(vici_parse_name(res), "key1");
+	ck_assert_str_eq(vici_parse_value_str(res), "value1");
+	ck_assert(vici_parse(res) == VICI_PARSE_KEY_VALUE);
+	ck_assert_str_eq(vici_parse_name(res), "key2");
+	str = vici_parse_value(res, &len);
+	ck_assert(chunk_equals(chunk_from_str("value2"), chunk_create(str, len)));
+	ck_assert(vici_parse(res) == VICI_PARSE_END_SECTION);
+	ck_assert(vici_parse(res) == VICI_PARSE_END);
+}
+
+static void encode_list(vici_req_t *req)
+{
+	vici_begin_list(req, "list1");
+	vici_add_list_item(req, "item1", strlen("item1"));
+	vici_add_list_itemf(req, "item%u", 2);
+	vici_end_list(req);
+}
+
+static void decode_list(vici_res_t *res)
+{
+	char *str;
+	int len;
+
+	ck_assert(vici_parse(res) == VICI_PARSE_BEGIN_LIST);
+	ck_assert_str_eq(vici_parse_name(res), "list1");
+	ck_assert(vici_parse(res) == VICI_PARSE_LIST_ITEM);
+	ck_assert_str_eq(vici_parse_value_str(res), "item1");
+	ck_assert(vici_parse(res) == VICI_PARSE_LIST_ITEM);
+	str = vici_parse_value(res, &len);
+	ck_assert(chunk_equals(chunk_from_str("item2"), chunk_create(str, len)));
+	ck_assert(vici_parse(res) == VICI_PARSE_END_LIST);
+	ck_assert(vici_parse(res) == VICI_PARSE_END);
+}
+
+static struct {
+	void (*encode)(vici_req_t* req);
+	void (*decode)(vici_res_t* res);
+} echo_tests[] = {
+	{ encode_section, decode_section },
+	{ encode_list, decode_list },
+};
+
+static vici_message_t* echo_cb(void *user, char *name,
+							   u_int id, vici_message_t *request)
+{
+	ck_assert_str_eq(name, "echo");
+	ck_assert_int_eq((uintptr_t)user, 1);
+
+	return vici_message_create_from_enumerator(request->create_enumerator(request));
+}
+
+START_TEST(test_echo)
+{
+	vici_dispatcher_t *dispatcher;
+	vici_conn_t *conn;
+	vici_req_t *req;
+	vici_res_t *res;
+
+	lib->processor->set_threads(lib->processor, 8);
+
+	dispatcher = vici_dispatcher_create(URI);
+	ck_assert(dispatcher);
+
+	dispatcher->manage_command(dispatcher, "echo", echo_cb, (void*)(uintptr_t)1);
+
+	vici_init();
+	conn = vici_connect(URI);
+	ck_assert(conn);
+
+	req = vici_begin("echo");
+	echo_tests[_i].encode(req);
+	res = vici_submit(req, conn);
+	ck_assert(res);
+	echo_tests[_i].decode(res);
+	vici_free_res(res);
+
+	vici_disconnect(conn);
+
+	dispatcher->manage_command(dispatcher, "echo", NULL, NULL);
+
+	lib->processor->cancel(lib->processor);
+	dispatcher->destroy(dispatcher);
+
+	vici_deinit();
+}
+END_TEST
+
+START_TEST(test_missing)
+{
+	vici_dispatcher_t *dispatcher;
+	vici_conn_t *conn;
+	vici_req_t *req;
+	vici_res_t *res;
+
+	lib->processor->set_threads(lib->processor, 8);
+
+	dispatcher = vici_dispatcher_create(URI);
+	ck_assert(dispatcher);
+
+	vici_init();
+	conn = vici_connect(URI);
+	ck_assert(conn);
+
+	req = vici_begin("nonexistent");
+	encode_section(req);
+	res = vici_submit(req, conn);
+	ck_assert(res == NULL);
+
+	vici_disconnect(conn);
+
+	dispatcher->manage_command(dispatcher, "echo", NULL, NULL);
+
+	lib->processor->cancel(lib->processor);
+	dispatcher->destroy(dispatcher);
+
+	vici_deinit();
+}
+END_TEST
+
+static void event_cb(void *user, char *name, vici_res_t *ev)
+{
+	int *events = (int*)user;
+
+	(*events)++;
+}
+
+START_TEST(test_stress)
+{
+	vici_dispatcher_t *dispatcher;
+	vici_conn_t *conn;
+	vici_req_t *req;
+	vici_res_t *res;
+	int i, total = 50, events = 0;
+
+	lib->processor->set_threads(lib->processor, 8);
+
+	dispatcher = vici_dispatcher_create(URI);
+	ck_assert(dispatcher);
+
+	dispatcher->manage_command(dispatcher, "echo", echo_cb, (void*)(uintptr_t)1);
+	dispatcher->manage_event(dispatcher, "dummy", TRUE);
+
+	vici_init();
+	conn = vici_connect(URI);
+	ck_assert(conn);
+
+	for (i = 0; i < total; i++)
+	{
+		/* do some event management in between */
+		ck_assert(vici_register(conn, "dummy", event_cb, &events) == 0);
+		dispatcher->raise_event(dispatcher, "dummy", 0,
+			vici_message_create_from_args(
+				 VICI_KEY_VALUE, "key1", chunk_from_str("value1"),
+				VICI_END));
+
+		req = vici_begin("echo");
+		encode_section(req);
+		res = vici_submit(req, conn);
+		ck_assert(res);
+		decode_section(res);
+		vici_free_res(res);
+
+		ck_assert(vici_register(conn, "dummy", NULL, NULL) == 0);
+	}
+
+	while (events < total)
+	{
+		usleep(1000);
+	}
+
+	vici_disconnect(conn);
+
+	dispatcher->manage_command(dispatcher, "echo", NULL, NULL);
+	dispatcher->manage_event(dispatcher, "dummy", FALSE);
+
+	lib->processor->cancel(lib->processor);
+	dispatcher->destroy(dispatcher);
+
+	vici_deinit();
+}
+END_TEST
+
+Suite *request_suite_create()
+{
+	Suite *s;
+	TCase *tc;
+
+	s = suite_create("vici request");
+
+	tc = tcase_create("echo");
+	tcase_add_loop_test(tc, test_echo, 0, countof(echo_tests));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("missing");
+	tcase_add_test(tc, test_missing);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("stress");
+	tcase_add_test(tc, test_stress);
+	suite_add_tcase(s, tc);
+
+	return s;
+}
diff --git a/src/libcharon/plugins/vici/suites/test_socket.c b/src/libcharon/plugins/vici/suites/test_socket.c
new file mode 100644
index 0000000..8d545c6
--- /dev/null
+++ b/src/libcharon/plugins/vici/suites/test_socket.c
@@ -0,0 +1,133 @@
+/*
+ * 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_suite.h>
+
+#include "../vici_socket.h"
+
+#include <unistd.h>
+
+typedef struct {
+	vici_socket_t *s;
+	int disconnect;
+	int bytes;
+	u_int id;
+} test_data_t;
+
+static void echo_inbound(void *user, u_int id, chunk_t buf)
+{
+	test_data_t *data = user;
+
+	ck_assert_int_eq(data->id, id);
+	/* count number of bytes, including the header */
+	data->bytes += buf.len + sizeof(u_int32_t);
+	/* echo back data chunk */
+	data->s->send(data->s, id, chunk_clone(buf));
+}
+
+static void echo_connect(void *user, u_int id)
+{
+	test_data_t *data = user;
+
+	data->id = id;
+}
+
+static void echo_disconnect(void *user, u_int id)
+{
+	test_data_t *data = user;
+
+	ck_assert(id == data->id);
+	data->disconnect++;
+}
+
+static struct {
+	char *uri;
+	u_int chunksize;
+} echo_tests[] = {
+	{ "tcp://127.0.0.1:6543", ~0 },
+	{ "tcp://127.0.0.1:6543",  1 },
+	{ "tcp://127.0.0.1:6543",  2 },
+	{ "tcp://127.0.0.1:6543",  3 },
+	{ "tcp://127.0.0.1:6543",  7 },
+#ifndef WIN32
+	{ "unix:///tmp/strongswan-tests-vici-socket", ~0 },
+	{ "unix:///tmp/strongswan-tests-vici-socket",  1 },
+	{ "unix:///tmp/strongswan-tests-vici-socket",  2 },
+	{ "unix:///tmp/strongswan-tests-vici-socket",  3 },
+	{ "unix:///tmp/strongswan-tests-vici-socket",  7 },
+#endif /* !WIN32 */
+};
+
+START_TEST(test_echo)
+{
+	stream_t *c;
+	test_data_t data = {};
+	chunk_t x, m = chunk_from_chars(
+		0x00,0x00,0x00,0x00,
+		0x00,0x00,0x00,0x01,	0x01,
+		0x00,0x00,0x00,0x05,	0x11,0x12,0x13,0x14,0x15,
+		0x00,0x00,0x00,0x0A,	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x02A,
+	);
+	char buf[m.len];
+	u_int32_t len;
+
+	lib->processor->set_threads(lib->processor, 4);
+
+	/* create socket, connect with stream */
+	data.s = vici_socket_create(echo_tests[_i].uri, echo_inbound, echo_connect,
+								echo_disconnect, &data);
+	ck_assert(data.s != NULL);
+	c = lib->streams->connect(lib->streams, echo_tests[_i].uri);
+	ck_assert(c != NULL);
+
+	/* write arbitrary chunks of messages blob depending on test */
+	x = m;
+	while (x.len)
+	{
+		len = min(x.len, echo_tests[_i].chunksize);
+		ck_assert(c->write_all(c, x.ptr, len));
+		x = chunk_skip(x, len);
+	}
+
+	/* verify echo */
+	ck_assert(c->read_all(c, buf, sizeof(buf)));
+	ck_assert(chunk_equals(m, chunk_from_thing(buf)));
+
+	/* wait for completion */
+	c->destroy(c);
+	while (data.disconnect != 1)
+	{
+		usleep(1000);
+	}
+	/* check that we got correct number of bytes/invocations */
+	ck_assert_int_eq(data.bytes, m.len);
+
+	data.s->destroy(data.s);
+}
+END_TEST
+
+Suite *socket_suite_create()
+{
+	Suite *s;
+	TCase *tc;
+
+	s = suite_create("vici socket");
+
+	tc = tcase_create("echo");
+	tcase_add_loop_test(tc, test_echo, 0, countof(echo_tests));
+	suite_add_tcase(s, tc);
+
+	return s;
+}
diff --git a/src/libcharon/plugins/vici/vici_attribute.c b/src/libcharon/plugins/vici/vici_attribute.c
new file mode 100644
index 0000000..2178116
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_attribute.c
@@ -0,0 +1,713 @@
+/*
+ * 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 "vici_attribute.h"
+#include "vici_builder.h"
+
+#include <daemon.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+#include <threading/rwlock.h>
+#include <attributes/mem_pool.h>
+
+typedef struct private_vici_attribute_t private_vici_attribute_t;
+
+/**
+ * private data of vici_attribute
+ */
+struct private_vici_attribute_t {
+
+	/**
+	 * public functions
+	 */
+	vici_attribute_t public;
+
+	/**
+	 * vici connection dispatcher
+	 */
+	vici_dispatcher_t *dispatcher;
+
+	/**
+	 * Configured pools, as char* => pool_t
+	 */
+	hashtable_t *pools;
+
+	/**
+	 * rwlock to lock access to pools
+	 */
+	rwlock_t *lock;
+};
+
+/**
+ * Single configuration attribute with type
+ */
+typedef struct {
+	/** type of attribute */
+	configuration_attribute_type_t type;
+	/** attribute value */
+	chunk_t value;
+} attribute_t;
+
+/**
+ * Clean up an attribute
+ */
+static void attribute_destroy(attribute_t *attr)
+{
+	free(attr->value.ptr);
+	free(attr);
+}
+
+/**
+ * Pool instances with associated attributes
+ */
+typedef struct {
+	/** in-memory virtual IP pool */
+	mem_pool_t *vips;
+	/** configuration attributes, as attribute_t */
+	array_t *attrs;
+} pool_t;
+
+/**
+ * Clean up a pool instance
+ */
+static void pool_destroy(pool_t *pool)
+{
+	DESTROY_IF(pool->vips);
+	array_destroy_function(pool->attrs, (void*)attribute_destroy, NULL);
+	free(pool);
+}
+
+/**
+ * Find an existing or not yet existing lease
+ */
+static host_t *find_addr(private_vici_attribute_t *this, linked_list_t *pools,
+					identification_t *id, host_t *requested, mem_pool_op_t op)
+{
+	enumerator_t *enumerator;
+	host_t *addr = NULL;
+	pool_t *pool;
+	char *name;
+
+	enumerator = pools->create_enumerator(pools);
+	while (enumerator->enumerate(enumerator, &name))
+	{
+		pool = this->pools->get(this->pools, name);
+		if (pool)
+		{
+			addr = pool->vips->acquire_address(pool->vips, id, requested, op);
+			if (addr)
+			{
+				break;
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	return addr;
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+	private_vici_attribute_t *this, linked_list_t *pools, identification_t *id,
+	host_t *requested)
+{
+	host_t *addr;
+
+	this->lock->read_lock(this->lock);
+
+	addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING);
+	if (!addr)
+	{
+		addr = find_addr(this, pools, id, requested, MEM_POOL_NEW);
+		if (!addr)
+		{
+			addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN);
+		}
+	}
+
+	this->lock->unlock(this->lock);
+
+	return addr;
+}
+
+METHOD(attribute_provider_t, release_address, bool,
+	private_vici_attribute_t *this, linked_list_t *pools, host_t *address,
+	identification_t *id)
+{
+	enumerator_t *enumerator;
+	bool found = FALSE;
+	pool_t *pool;
+	char *name;
+
+	this->lock->read_lock(this->lock);
+
+	enumerator = pools->create_enumerator(pools);
+	while (enumerator->enumerate(enumerator, &name))
+	{
+		pool = this->pools->get(this->pools, name);
+		if (pool)
+		{
+			found = pool->vips->release_address(pool->vips, address, id);
+			if (found)
+			{
+				break;
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	this->lock->unlock(this->lock);
+
+	return found;
+}
+
+/**
+ * Filter mapping attribute_t to enumerated type/value arguments
+ */
+static bool attr_filter(void *data, attribute_t **attr,
+						configuration_attribute_type_t *type,
+						void *in, chunk_t *value)
+{
+	*type = (*attr)->type;
+	*value = (*attr)->value;
+	return TRUE;
+}
+
+/**
+ * Create nested inner enumerator over pool attributes
+ */
+CALLBACK(create_nested, enumerator_t*,
+	pool_t *pool, void *this)
+{
+	return enumerator_create_filter(array_create_enumerator(pool->attrs),
+									(void*)attr_filter, NULL, NULL);
+}
+
+/**
+ * Data associated to nested enumerator cleanup
+ */
+typedef struct {
+	private_vici_attribute_t *this;
+	linked_list_t *list;
+} nested_data_t;
+
+/**
+ * Clean up nested enumerator data
+ */
+CALLBACK(nested_cleanup, void,
+	nested_data_t *data)
+{
+	data->this->lock->unlock(data->this->lock);
+	data->list->destroy(data->list);
+	free(data);
+}
+
+/**
+ * Check if any of vips is from pool
+ */
+static bool have_vips_from_pool(mem_pool_t *pool, linked_list_t *vips)
+{
+	enumerator_t *enumerator;
+	host_t *host;
+	chunk_t start, end, current;
+	u_int32_t size;
+	bool found = FALSE;
+
+	host = pool->get_base(pool);
+	start = host->get_address(host);
+
+	if (start.len >= sizeof(size))
+	{
+		end = chunk_clone(start);
+
+		/* mem_pool is currenty limited to 2^31 addresses, so 32-bit
+		 * calculations should be sufficient. */
+		size = untoh32(start.ptr + start.len - sizeof(size));
+		htoun32(end.ptr + end.len - sizeof(size), size + pool->get_size(pool));
+
+		enumerator = vips->create_enumerator(vips);
+		while (enumerator->enumerate(enumerator, &host))
+		{
+			current = host->get_address(host);
+			if (chunk_compare(current, start) >= 0 &&
+				chunk_compare(current, end) < 0)
+			{
+				found = TRUE;
+				break;
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		free(end.ptr);
+	}
+	return found;
+}
+
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+	private_vici_attribute_t *this, linked_list_t *pools,
+	identification_t *id, linked_list_t *vips)
+{
+	enumerator_t *enumerator;
+	nested_data_t *data;
+	pool_t *pool;
+	char *name;
+
+	INIT(data,
+		.this = this,
+		.list = linked_list_create(),
+	);
+
+	this->lock->read_lock(this->lock);
+
+	enumerator = pools->create_enumerator(pools);
+	while (enumerator->enumerate(enumerator, &name))
+	{
+		pool = this->pools->get(this->pools, name);
+		if (pool && have_vips_from_pool(pool->vips, vips))
+		{
+			data->list->insert_last(data->list, pool);
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	return enumerator_create_nested(data->list->create_enumerator(data->list),
+									create_nested, data, nested_cleanup);
+}
+
+/**
+ * Merge a pool configuration with existing ones
+ */
+static bool merge_pool(private_vici_attribute_t *this, pool_t *new)
+{
+	mem_pool_t *tmp;
+	host_t *base;
+	pool_t *old;
+	const char *name;
+	u_int size;
+
+	name = new->vips->get_name(new->vips);
+	base = new->vips->get_base(new->vips);
+	size = new->vips->get_size(new->vips);
+
+	old = this->pools->remove(this->pools, name);
+	if (!old)
+	{
+		this->pools->put(this->pools, name, new);
+		DBG1(DBG_CFG, "added vici pool %s: %H, %u entries", name, base, size);
+		return TRUE;
+	}
+
+	if (base->ip_equals(base, old->vips->get_base(old->vips)) &&
+		size == old->vips->get_size(old->vips))
+	{
+		/* no changes in pool, so keep existing, but use new attributes */
+		DBG1(DBG_CFG, "updated vici pool %s: %H, %u entries", name, base, size);
+		tmp = new->vips;
+		new->vips = old->vips;
+		old->vips = tmp;
+		this->pools->put(this->pools, new->vips->get_name(new->vips), new);
+		pool_destroy(old);
+		return TRUE;
+	}
+	if (old->vips->get_online(old->vips) == 0)
+	{
+		/* can replace old pool, no online leases */
+		DBG1(DBG_CFG, "replaced vici pool %s: %H, %u entries", name, base, size);
+		this->pools->put(this->pools, name, new);
+		pool_destroy(old);
+		return TRUE;
+	}
+	/* have online leases, unable to replace, TODO: migrate leases? */
+	DBG1(DBG_CFG, "vici pool %s has %u online leases, unable to replace",
+		 name, old->vips->get_online(old->vips));
+	this->pools->put(this->pools, old->vips->get_name(old->vips), old);
+	return FALSE;
+}
+
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+	vici_builder_t *builder;
+	va_list args;
+
+	builder = vici_builder_create();
+	builder->add_kv(builder, "success", fmt ? "no" : "yes");
+	if (fmt)
+	{
+		va_start(args, fmt);
+		builder->vadd_kv(builder, "errmsg", fmt, args);
+		va_end(args);
+	}
+	return builder->finalize(builder);
+}
+
+/**
+ * Parse callback data, passed to each callback
+ */
+typedef struct {
+	private_vici_attribute_t *this;
+	vici_message_t *reply;
+} request_data_t;
+
+/**
+ * Data associated to a pool load
+ */
+typedef struct {
+	request_data_t *request;
+	char *name;
+	pool_t *pool;
+} load_data_t;
+
+CALLBACK(pool_li, bool,
+	load_data_t *data, vici_message_t *message, char *name, chunk_t value)
+{
+	struct {
+		char *name;
+		configuration_attribute_type_t v4;
+		configuration_attribute_type_t v6;
+	} 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			},
+	};
+	char buf[256];
+	int i, index = -1, mask = -1, type = 0;
+	chunk_t encoding;
+	attribute_t *attr;
+	host_t *host = NULL;
+
+	for (i = 0; i < countof(keys); i++)
+	{
+		if (streq(name, keys[i].name))
+		{
+			index = i;
+			break;
+		}
+	}
+	if (index == -1)
+	{
+		type = atoi(name);
+		if (!type)
+		{
+			data->request->reply = create_reply("invalid attribute: %s", name);
+			return FALSE;
+		}
+	}
+
+	if (vici_stringify(value, buf, sizeof(buf)))
+	{
+		if (strchr(buf, '/'))
+		{
+			host = host_create_from_subnet(buf, &mask);
+		}
+		else
+		{
+			host = host_create_from_string(buf, 0);
+		}
+	}
+	if (host)
+	{
+		if (index != -1)
+		{
+			switch (host->get_family(host))
+			{
+				case AF_INET:
+					type = keys[index].v4;
+					break;
+				case AF_INET6:
+				default:
+					type = keys[index].v6;
+					break;
+			}
+		}
+		if (mask == -1)
+		{
+			encoding = chunk_clone(host->get_address(host));
+		}
+		else
+		{
+			if (host->get_family(host) == AF_INET)
+			{	/* IPv4 attributes contain a subnet mask */
+				u_int32_t netmask = 0;
+
+				if (mask)
+				{	/* shifting u_int32_t by 32 or more is undefined */
+					mask = 32 - mask;
+					netmask = htonl((0xFFFFFFFF >> mask) << mask);
+				}
+				encoding = chunk_cat("cc", host->get_address(host),
+									 chunk_from_thing(netmask));
+			}
+			else
+			{	/* IPv6 addresses the prefix only */
+				encoding = chunk_cat("cc", host->get_address(host),
+									 chunk_from_chars(mask));
+			}
+		}
+		host->destroy(host);
+	}
+	else
+	{
+		if (index != -1)
+		{
+			data->request->reply = create_reply("invalid attribute value "
+												"for %s", name);
+			return FALSE;
+		}
+		/* use raw binary data for numbered attributes */
+		encoding = chunk_clone(value);
+	}
+	INIT(attr,
+		.type = type,
+		.value = encoding,
+	);
+	array_insert_create(&data->pool->attrs, ARRAY_TAIL, attr);
+	return TRUE;
+}
+
+CALLBACK(pool_kv, bool,
+	load_data_t *data, vici_message_t *message, char *name, chunk_t value)
+{
+	if (streq(name, "addrs"))
+	{
+		char buf[128];
+		host_t *base;
+		int bits;
+
+		if (data->pool->vips)
+		{
+			data->request->reply = create_reply("multiple addrs defined");
+			return FALSE;
+		}
+		if (!vici_stringify(value, buf, sizeof(buf)))
+		{
+			data->request->reply = create_reply("invalid addrs value");
+			return FALSE;
+		}
+		base = host_create_from_subnet(buf, &bits);
+		if (!base)
+		{
+			data->request->reply = create_reply("invalid addrs value: %s", buf);
+			return FALSE;
+		}
+		data->pool->vips = mem_pool_create(data->name, base, bits);
+		base->destroy(base);
+		return TRUE;
+	}
+	data->request->reply = create_reply("invalid attribute: %s", name);
+	return FALSE;
+}
+
+CALLBACK(pool_sn, bool,
+	request_data_t *request, vici_message_t *message,
+	vici_parse_context_t *ctx, char *name)
+{
+	load_data_t data = {
+		.request = request,
+		.name = name,
+	};
+	bool merged;
+
+	INIT(data.pool);
+
+	if (!message->parse(message, ctx, NULL, pool_kv, pool_li, &data))
+	{
+		pool_destroy(data.pool);
+		return FALSE;
+	}
+
+	if (!data.pool->vips)
+	{
+		request->reply = create_reply("missing addrs for pool '%s'", name);
+		pool_destroy(data.pool);
+		return FALSE;
+	}
+
+	request->this->lock->write_lock(request->this->lock);
+	merged = merge_pool(request->this, data.pool);
+	request->this->lock->unlock(request->this->lock);
+
+	if (!merged)
+	{
+		request->reply = create_reply("vici pool %s has online leases, "
+									  "unable to replace", name);
+		pool_destroy(data.pool);
+	}
+	return merged;
+}
+
+CALLBACK(load_pool, vici_message_t*,
+	private_vici_attribute_t *this, char *name, u_int id,
+	vici_message_t *message)
+{
+	request_data_t request = {
+		.this = this,
+	};
+
+	if (!message->parse(message, NULL, pool_sn, NULL, NULL, &request))
+	{
+		if (request.reply)
+		{
+			return request.reply;
+		}
+		return create_reply("parsing request failed");
+	}
+	return create_reply(NULL);
+}
+
+CALLBACK(unload_pool, vici_message_t*,
+	private_vici_attribute_t *this, char *name, u_int id,
+	vici_message_t *message)
+{
+	vici_message_t *reply;
+	u_int online;
+	pool_t *pool;
+
+	name = message->get_str(message, NULL, "name");
+	if (!name)
+	{
+		return create_reply("missing pool name to unload");
+	}
+
+	this->lock->write_lock(this->lock);
+
+	pool = this->pools->remove(this->pools, name);
+	if (pool)
+	{
+		online = pool->vips->get_online(pool->vips);
+		if (online)
+		{
+			DBG1(DBG_CFG, "vici pool %s has %u online leases, unable to unload",
+				 name, online);
+			reply = create_reply("%s has online leases, unable to unload", name);
+			this->pools->put(this->pools, pool->vips->get_name(pool->vips), pool);
+		}
+		else
+		{
+			DBG1(DBG_CFG, "unloaded vici pool %s", name);
+			reply = create_reply(NULL);
+			pool_destroy(pool);
+		}
+	}
+	else
+	{
+		reply = create_reply("%s not found", name);
+	}
+
+	this->lock->unlock(this->lock);
+
+	return reply;
+}
+
+CALLBACK(get_pools, vici_message_t*,
+	private_vici_attribute_t *this, char *name, u_int id,
+	vici_message_t *message)
+{
+	vici_builder_t *builder;
+	enumerator_t *enumerator;
+	mem_pool_t *vips;
+	pool_t *pool;
+
+	builder = vici_builder_create();
+
+	this->lock->read_lock(this->lock);
+	enumerator = this->pools->create_enumerator(this->pools);
+	while (enumerator->enumerate(enumerator, &name, &pool))
+	{
+		vips = pool->vips;
+
+		builder->begin_section(builder, name);
+
+		builder->add_kv(builder, "base", "%H", vips->get_base(vips));
+		builder->add_kv(builder, "size", "%u", vips->get_size(vips));
+		builder->add_kv(builder, "online", "%u", vips->get_online(vips));
+		builder->add_kv(builder, "offline", "%u", vips->get_offline(vips));
+
+		builder->end_section(builder);
+	}
+	enumerator->destroy(enumerator);
+	this->lock->unlock(this->lock);
+
+	return builder->finalize(builder);
+}
+
+static void manage_command(private_vici_attribute_t *this,
+						   char *name, vici_command_cb_t cb, bool reg)
+{
+	this->dispatcher->manage_command(this->dispatcher, name,
+									 reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_attribute_t *this, bool reg)
+{
+	manage_command(this, "load-pool", load_pool, reg);
+	manage_command(this, "unload-pool", unload_pool, reg);
+	manage_command(this, "get-pools", get_pools, reg);
+}
+
+METHOD(vici_attribute_t, destroy, void,
+	private_vici_attribute_t *this)
+{
+	enumerator_t *enumerator;
+	pool_t *pool;
+
+	manage_commands(this, FALSE);
+
+	enumerator = this->pools->create_enumerator(this->pools);
+	while (enumerator->enumerate(enumerator, NULL, &pool))
+	{
+		pool_destroy(pool);
+	}
+	enumerator->destroy(enumerator);
+	this->pools->destroy(this->pools);
+	this->lock->destroy(this->lock);
+	free(this);
+}
+
+/*
+ * see header file
+ */
+vici_attribute_t *vici_attribute_create(vici_dispatcher_t *dispatcher)
+{
+	private_vici_attribute_t *this;
+
+	INIT(this,
+		.public = {
+			.provider = {
+				.acquire_address = _acquire_address,
+				.release_address = _release_address,
+				.create_attribute_enumerator = _create_attribute_enumerator,
+			},
+			.destroy = _destroy,
+		},
+		.dispatcher = dispatcher,
+		.pools = hashtable_create(hashtable_hash_str, hashtable_equals_str, 4),
+		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+	);
+
+	manage_commands(this, TRUE);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_attribute.h b/src/libcharon/plugins/vici/vici_attribute.h
new file mode 100644
index 0000000..652a96d
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_attribute.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup vici_attribute vici_attribute
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_ATTRIBUTE_H_
+#define VICI_ATTRIBUTE_H_
+
+#include "vici_dispatcher.h"
+
+#include <attributes/attribute_provider.h>
+
+typedef struct vici_attribute_t vici_attribute_t;
+
+/**
+ * IKE configuration attribute backend for vici.
+ */
+struct vici_attribute_t {
+
+	/**
+	 * Implements attribute provider interface
+	 */
+	attribute_provider_t provider;
+
+	/**
+	 * Destroy a vici_attribute_t.
+	 */
+	void (*destroy)(vici_attribute_t *this);
+};
+
+/**
+ * Create a vici_attribute instance.
+ *
+ * @param dispatcher		vici dispatcher context
+ * @return					vici attribute handler
+ */
+vici_attribute_t *vici_attribute_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_ATTRIBUTE_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_builder.c b/src/libcharon/plugins/vici/vici_builder.c
new file mode 100644
index 0000000..5616320
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_builder.c
@@ -0,0 +1,253 @@
+/*
+ * 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 "vici_builder.h"
+
+#include <bio/bio_writer.h>
+
+typedef struct private_vici_builder_t private_vici_builder_t;
+
+/**
+ * Private data of an vici_builder_t object.
+ */
+struct private_vici_builder_t {
+
+	/**
+	 * Public vici_builder_t interface.
+	 */
+	vici_builder_t public;
+
+	/**
+	 * Writer for elements
+	 */
+	bio_writer_t *writer;
+
+	/**
+	 * Errors encountered
+	 */
+	u_int error;
+
+	/**
+	 * Section nesting level
+	 */
+	u_int section;
+
+	/**
+	 * In list element?
+	 */
+	bool list;
+};
+
+METHOD(vici_builder_t, add, void,
+	private_vici_builder_t *this, vici_type_t type, ...)
+{
+	va_list args;
+	char *name = NULL;
+	chunk_t value = chunk_empty;
+
+	va_start(args, type);
+	switch (type)
+	{
+		case VICI_SECTION_END:
+		case VICI_LIST_END:
+		case VICI_END:
+			break;
+		case VICI_LIST_START:
+		case VICI_SECTION_START:
+			name = va_arg(args, char*);
+			break;
+		case VICI_KEY_VALUE:
+			name = va_arg(args, char*);
+			value = va_arg(args, chunk_t);
+			break;
+		case VICI_LIST_ITEM:
+			value = va_arg(args, chunk_t);
+			break;
+		default:
+			va_end(args);
+			this->error++;
+			return;
+	}
+	va_end(args);
+
+	if (value.len > 0xffff)
+	{
+		this->error++;
+		return;
+	}
+	if (!vici_verify_type(type, this->section, this->list))
+	{
+		this->error++;
+		return;
+	}
+	if (type != VICI_END)
+	{
+		this->writer->write_uint8(this->writer, type);
+	}
+	switch (type)
+	{
+		case VICI_SECTION_START:
+			this->writer->write_data8(this->writer, chunk_from_str(name));
+			this->section++;
+			break;
+		case VICI_SECTION_END:
+			this->section--;
+			break;
+		case VICI_KEY_VALUE:
+			this->writer->write_data8(this->writer, chunk_from_str(name));
+			this->writer->write_data16(this->writer, value);
+			break;
+		case VICI_LIST_START:
+			this->writer->write_data8(this->writer, chunk_from_str(name));
+			this->list = TRUE;
+			break;
+		case VICI_LIST_ITEM:
+			this->writer->write_data16(this->writer, value);
+			break;
+		case VICI_LIST_END:
+			this->list = FALSE;
+			break;
+		default:
+			this->error++;
+			break;
+	}
+}
+
+METHOD(vici_builder_t, vadd_kv, void,
+	private_vici_builder_t *this, char *key, char *fmt, va_list args)
+{
+	char buf[2048];
+	ssize_t len;
+
+	len = vsnprintf(buf, sizeof(buf), fmt, args);
+	if (len < 0 || len >= sizeof(buf))
+	{
+		DBG1(DBG_ENC, "vici builder format buffer exceeds limit");
+		this->error++;
+	}
+	else
+	{
+		add(this, VICI_KEY_VALUE, key, chunk_create(buf, len));
+	}
+}
+
+METHOD(vici_builder_t, add_kv, void,
+	private_vici_builder_t *this, char *key, char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vadd_kv(this, key, fmt, args);
+	va_end(args);
+}
+
+
+METHOD(vici_builder_t, vadd_li, void,
+	private_vici_builder_t *this, char *fmt, va_list args)
+{
+	char buf[2048];
+	ssize_t len;
+
+	len = vsnprintf(buf, sizeof(buf), fmt, args);
+	if (len < 0 || len >= sizeof(buf))
+	{
+		DBG1(DBG_ENC, "vici builder format buffer exceeds limit");
+		this->error++;
+	}
+	else
+	{
+		add(this, VICI_LIST_ITEM, chunk_create(buf, len));
+	}
+}
+
+METHOD(vici_builder_t, add_li, void,
+	private_vici_builder_t *this, char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vadd_li(this, fmt, args);
+	va_end(args);
+}
+
+METHOD(vici_builder_t, begin_section, void,
+	private_vici_builder_t *this, char *name)
+{
+	add(this, VICI_SECTION_START, name);
+}
+
+METHOD(vici_builder_t, end_section, void,
+	private_vici_builder_t *this)
+{
+	add(this, VICI_SECTION_END);
+}
+
+METHOD(vici_builder_t, begin_list, void,
+	private_vici_builder_t *this, char *name)
+{
+	add(this, VICI_LIST_START, name);
+}
+
+METHOD(vici_builder_t, end_list, void,
+	private_vici_builder_t *this)
+{
+	add(this, VICI_LIST_END);
+}
+
+METHOD(vici_builder_t, finalize, vici_message_t*,
+	private_vici_builder_t *this)
+{
+	vici_message_t *product;
+
+	if (this->error || this->section || this->list)
+	{
+		DBG1(DBG_ENC, "vici builder error: %u errors (section: %u, list %u)",
+			 this->error, this->section, this->list);
+		this->writer->destroy(this->writer);
+		free(this);
+		return NULL;
+	}
+	product = vici_message_create_from_data(
+								this->writer->extract_buf(this->writer), TRUE);
+	this->writer->destroy(this->writer);
+	free(this);
+	return product;
+}
+
+/**
+ * See header
+ */
+vici_builder_t *vici_builder_create()
+{
+	private_vici_builder_t *this;
+
+	INIT(this,
+		.public = {
+			.add = _add,
+			.add_kv = _add_kv,
+			.vadd_kv = _vadd_kv,
+			.add_li = _add_li,
+			.vadd_li = _vadd_li,
+			.begin_section = _begin_section,
+			.end_section = _end_section,
+			.begin_list = _begin_list,
+			.end_list = _end_list,
+			.finalize = _finalize,
+		},
+		.writer = bio_writer_create(0),
+	);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_builder.h b/src/libcharon/plugins/vici/vici_builder.h
new file mode 100644
index 0000000..5a5cc8a
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_builder.h
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup vici_builder vici_builder
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_BUILDER_H_
+#define VICI_BUILDER_H_
+
+#include "vici_message.h"
+
+typedef struct vici_builder_t vici_builder_t;
+
+/**
+ * Build helper for vici message
+ */
+struct vici_builder_t {
+
+	/**
+	 * Append a generic message element to message.
+	 *
+	 * The additional arguments are type specific, it may be nothing, a string,
+	 * a chunk value or both.
+	 *
+	 * @param type	element type to add
+	 * @param ...	additional type specific arguments
+	 */
+	void (*add)(vici_builder_t *this, vici_type_t type, ...);
+
+	/**
+	 * Append a key/value element using a format string.
+	 *
+	 * Instead of passing the type specific value as a chunk, this method
+	 * takes a printf() style format string followed by its arguments. The
+	 * key name for a key/value type is still a fixed string.
+	 *
+	 * @param key	key name of the key/value to add
+	 * @param fmt	value format string
+	 * @param ...	arguments to value format string
+	 */
+	void (*add_kv)(vici_builder_t *this, char *key, char *fmt, ...);
+
+	/**
+	 * Append a message element using a format string and va_list.
+	 *
+	 * Instead of passing the type specific value as a chunk, this method
+	 * takes a printf() style format string followed by its arguments. The
+	 * key name for a key/value type is still a fixed string.
+	 *
+	 * @param key	key name of the key/value to add
+	 * @param fmt	value format string
+	 * @param args	arguments to value format string
+	 */
+	void (*vadd_kv)(vici_builder_t *this, char *key, char *fmt, va_list args);
+
+	/**
+	 * Append a list item element using a format string.
+	 *
+	 * Instead of passing the type specific value as a chunk, this method
+	 * takes a printf() style format string followed by its arguments.
+	 *
+	 * @param fmt	value format string
+	 * @param ...	arguments to value format string
+	 */
+	void (*add_li)(vici_builder_t *this, char *fmt, ...);
+
+	/**
+	 * Append a list item element using a format string and va_list.
+	 *
+	 * Instead of passing the type specific value as a chunk, this method
+	 * takes a printf() style format string followed by its arguments.
+	 *
+	 * @param fmt	value format string
+	 * @param args	arguments to value format string
+	 */
+	void (*vadd_li)(vici_builder_t *this, char *fmt, va_list args);
+
+	/**
+	 * Begin a new section.
+	 *
+	 * @param name	name of section to begin
+	 */
+	void (*begin_section)(vici_builder_t *this, char *name);
+
+	/**
+	 * End the currently open section.
+	 */
+	void (*end_section)(vici_builder_t *this);
+
+	/**
+	 * Begin a new list.
+	 *
+	 * @param name	name of list to begin
+	 */
+	void (*begin_list)(vici_builder_t *this, char *name);
+
+	/**
+	 * End the currently open list.
+	 */
+	void (*end_list)(vici_builder_t *this);
+
+	/**
+	 * Finalize a vici message with all added elements, destroy builder.
+	 *
+	 * @return		vici message, NULL on error
+	 */
+	vici_message_t* (*finalize)(vici_builder_t *this);
+};
+
+/**
+ * Create a vici_builder instance.
+ */
+vici_builder_t *vici_builder_create();
+
+#endif /** VICI_BUILDER_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
new file mode 100644
index 0000000..113d480
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -0,0 +1,2006 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include "vici_config.h"
+#include "vici_builder.h"
+
+#include <daemon.h>
+#include <threading/rwlock.h>
+#include <collections/array.h>
+#include <collections/linked_list.h>
+
+#include <stdio.h>
+
+/**
+ * Magic value for an undefined lifetime
+ */
+#define LFT_UNDEFINED (~(u_int64_t)0)
+
+/**
+ * Default IKE rekey time
+ */
+#define LFT_DEFAULT_IKE_REKEY (4 * 60 * 60)
+
+/**
+ * Default CHILD rekey time
+ */
+#define LFT_DEFAULT_CHILD_REKEY (1 * 60 * 60)
+
+/**
+ * Undefined replay window
+ */
+#define REPLAY_UNDEFINED (~(u_int32_t)0)
+
+typedef struct private_vici_config_t private_vici_config_t;
+
+/**
+ * Private data of an vici_config_t object.
+ */
+struct private_vici_config_t {
+
+	/**
+	 * Public vici_config_t interface.
+	 */
+	vici_config_t public;
+
+	/**
+	 * Dispatcher
+	 */
+	vici_dispatcher_t *dispatcher;
+
+	/**
+	 * List of loaded connections, as peer_cfg_t
+	 */
+	linked_list_t *conns;
+
+	/**
+	 * Lock for conns list
+	 */
+	rwlock_t *lock;
+};
+
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+	private_vici_config_t *this, identification_t *me, identification_t *other)
+{
+	this->lock->read_lock(this->lock);
+	return enumerator_create_cleaner(this->conns->create_enumerator(this->conns),
+									 (void*)this->lock->unlock, this->lock);
+}
+
+/**
+ * Enumerator filter function for ike configs
+ */
+static bool ike_filter(void *data, peer_cfg_t **in, ike_cfg_t **out)
+{
+	*out = (*in)->get_ike_cfg(*in);
+	return TRUE;
+}
+
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+	private_vici_config_t *this, host_t *me, host_t *other)
+{
+	this->lock->read_lock(this->lock);
+	return enumerator_create_filter(this->conns->create_enumerator(this->conns),
+									(void*)ike_filter, this->lock,
+									(void*)this->lock->unlock);
+}
+
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+	private_vici_config_t *this, char *name)
+{
+	peer_cfg_t *current, *found = NULL;
+	enumerator_t *enumerator;
+
+	this->lock->read_lock(this->lock);
+	enumerator = this->conns->create_enumerator(this->conns);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (streq(current->get_name(current), name))
+		{
+			found = current;
+			found->get_ref(found);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->lock->unlock(this->lock);
+
+	return found;
+}
+
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+	vici_builder_t *builder;
+	va_list args;
+
+	builder = vici_builder_create();
+	builder->add_kv(builder, "success", fmt ? "no" : "yes");
+	if (fmt)
+	{
+		va_start(args, fmt);
+		builder->vadd_kv(builder, "errmsg", fmt, args);
+		va_end(args);
+	}
+	return builder->finalize(builder);
+}
+
+/**
+ * A rule to parse a key/value or list item
+ */
+typedef struct {
+	/** name of the key/value or list */
+	char *name;
+	/** function to parse value */
+	bool (*parse)(void *out, chunk_t value);
+	/** result, passed to parse() */
+	void *out;
+} parse_rule_t;
+
+/**
+ * Parse key/values using a rule-set
+ */
+static bool parse_rules(parse_rule_t *rules, int count, char *name,
+						chunk_t value, vici_message_t **reply)
+{
+	int i;
+
+	for (i = 0; i < count; i++)
+	{
+		if (streq(name, rules[i].name))
+		{
+			if (rules[i].parse(rules[i].out, value))
+			{
+				return TRUE;
+			}
+			*reply = create_reply("invalid value for: %s, config discarded",
+								  name);
+			return FALSE;
+		}
+	}
+	*reply = create_reply("unknown option: %s, config discarded", name);
+	return FALSE;
+}
+
+/**
+ * Parse callback data, passed to each callback
+ */
+typedef struct {
+	private_vici_config_t *this;
+	vici_message_t *reply;
+} request_data_t;
+
+/**
+ * Data associated to a peer config
+ */
+typedef struct {
+	request_data_t *request;
+	u_int32_t version;
+	bool aggressive;
+	bool encap;
+	bool mobike;
+	bool send_certreq;
+	bool pull;
+	cert_policy_t send_cert;
+	u_int64_t dpd_delay;
+	u_int64_t dpd_timeout;
+	fragmentation_t fragmentation;
+	unique_policy_t unique;
+	u_int32_t keyingtries;
+	u_int32_t local_port;
+	u_int32_t remote_port;
+	char *local_addrs;
+	char *remote_addrs;
+	linked_list_t *local;
+	linked_list_t *remote;
+	linked_list_t *proposals;
+	linked_list_t *children;
+	linked_list_t *vips;
+	char *pools;
+	u_int64_t reauth_time;
+	u_int64_t rekey_time;
+	u_int64_t over_time;
+	u_int64_t rand_time;
+} peer_data_t;
+
+/**
+ * Log relevant auth config data
+ */
+static void log_auth(auth_cfg_t *auth)
+{
+	enumerator_t *enumerator;
+	auth_rule_t rule;
+	union {
+		uintptr_t u;
+		identification_t *id;
+		char *str;
+	} v;
+
+	enumerator = auth->create_enumerator(auth);
+	while (enumerator->enumerate(enumerator, &rule, &v))
+	{
+		switch (rule)
+		{
+			case AUTH_RULE_AUTH_CLASS:
+				DBG2(DBG_CFG, "   class = %N", auth_class_names, v.u);
+				break;
+			case AUTH_RULE_EAP_TYPE:
+				DBG2(DBG_CFG, "   eap-type = %N", eap_type_names, v.u);
+				break;
+			case AUTH_RULE_EAP_VENDOR:
+				DBG2(DBG_CFG, "   eap-vendor = %u", v.u);
+				break;
+			case AUTH_RULE_XAUTH_BACKEND:
+				DBG2(DBG_CFG, "   xauth = %s", v.str);
+				break;
+			case AUTH_RULE_CRL_VALIDATION:
+				DBG2(DBG_CFG, "   revocation = %N", cert_validation_names, v.u);
+				break;
+			case AUTH_RULE_IDENTITY:
+				DBG2(DBG_CFG, "   id = %Y", v.id);
+				break;
+			case AUTH_RULE_AAA_IDENTITY:
+				DBG2(DBG_CFG, "   aaa_id = %Y", v.id);
+				break;
+			case AUTH_RULE_EAP_IDENTITY:
+				DBG2(DBG_CFG, "   eap_id = %Y", v.id);
+				break;
+			case AUTH_RULE_XAUTH_IDENTITY:
+				DBG2(DBG_CFG, "   xauth_id = %Y", v.id);
+				break;
+			case AUTH_RULE_GROUP:
+				DBG2(DBG_CFG, "   group = %Y", v.id);
+				break;
+			default:
+				break;
+		}
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Log parsed peer data
+ */
+static void log_peer_data(peer_data_t *data)
+{
+	enumerator_t *enumerator;
+	auth_cfg_t *auth;
+	host_t *host;
+
+	DBG2(DBG_CFG, "  version = %u", data->version);
+	DBG2(DBG_CFG, "  local_addrs = %s", data->local_addrs);
+	DBG2(DBG_CFG, "  remote_addrs = %s", data->remote_addrs);
+	DBG2(DBG_CFG, "  local_port = %u", data->local_port);
+	DBG2(DBG_CFG, "  remote_port = %u", data->remote_port);
+	DBG2(DBG_CFG, "  send_certreq = %u", data->send_certreq);
+	DBG2(DBG_CFG, "  send_cert = %N", cert_policy_names, data->send_cert);
+	DBG2(DBG_CFG, "  mobike = %u", data->mobike);
+	DBG2(DBG_CFG, "  aggressive = %u", data->aggressive);
+	DBG2(DBG_CFG, "  encap = %u", data->encap);
+	DBG2(DBG_CFG, "  dpd_delay = %llu", data->dpd_delay);
+	DBG2(DBG_CFG, "  dpd_timeout = %llu", data->dpd_timeout);
+	DBG2(DBG_CFG, "  fragmentation = %u",  data->fragmentation);
+	DBG2(DBG_CFG, "  unique = %N", unique_policy_names, data->unique);
+	DBG2(DBG_CFG, "  keyingtries = %u", data->keyingtries);
+	DBG2(DBG_CFG, "  reauth_time = %llu", data->reauth_time);
+	DBG2(DBG_CFG, "  rekey_time = %llu", data->rekey_time);
+	DBG2(DBG_CFG, "  over_time = %llu", data->over_time);
+	DBG2(DBG_CFG, "  rand_time = %llu", data->rand_time);
+	DBG2(DBG_CFG, "  proposals = %#P", data->proposals);
+
+	if (data->vips->get_count(data->vips))
+	{
+		DBG2(DBG_CFG, "  vips:");
+	}
+	enumerator = data->vips->create_enumerator(data->vips);
+	while (enumerator->enumerate(enumerator, &host))
+	{
+		DBG2(DBG_CFG, "   %H", host);
+	}
+	enumerator->destroy(enumerator);
+
+	enumerator = data->local->create_enumerator(data->local);
+	while (enumerator->enumerate(enumerator, &auth))
+	{
+		DBG2(DBG_CFG, "  local:");
+		log_auth(auth);
+	}
+	enumerator->destroy(enumerator);
+
+	enumerator = data->remote->create_enumerator(data->remote);
+	while (enumerator->enumerate(enumerator, &auth))
+	{
+		DBG2(DBG_CFG, "  remote:");
+		log_auth(auth);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Clean up peer config 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->children->destroy_offset(data->children,
+									offsetof(child_cfg_t, destroy));
+	data->proposals->destroy_offset(data->proposals,
+									offsetof(proposal_t, destroy));
+	data->vips->destroy_offset(data->vips, offsetof(host_t, destroy));
+	free(data->pools);
+	free(data->local_addrs);
+	free(data->remote_addrs);
+}
+
+/**
+ * CHILD config data
+ */
+typedef struct {
+	request_data_t *request;
+	lifetime_cfg_t lft;
+	char* updown;
+	bool hostaccess;
+	bool ipcomp;
+	bool route;
+	ipsec_mode_t mode;
+	u_int32_t replay_window;
+	action_t dpd_action;
+	action_t start_action;
+	action_t close_action;
+	u_int32_t reqid;
+	u_int32_t tfc;
+	mark_t mark_in;
+	mark_t mark_out;
+	u_int64_t inactivity;
+	linked_list_t *proposals;
+	linked_list_t *local_ts;
+	linked_list_t *remote_ts;
+} child_data_t;
+
+/**
+ * Log parsed CHILD config data
+ */
+static void log_child_data(child_data_t *data, char *name)
+{
+	DBG2(DBG_CFG, "  child %s:", name);
+	DBG2(DBG_CFG, "   rekey_time = %llu", data->lft.time.rekey);
+	DBG2(DBG_CFG, "   life_time = %llu", data->lft.time.life);
+	DBG2(DBG_CFG, "   rand_time = %llu", data->lft.time.jitter);
+	DBG2(DBG_CFG, "   rekey_bytes = %llu", data->lft.bytes.rekey);
+	DBG2(DBG_CFG, "   life_bytes = %llu", data->lft.bytes.life);
+	DBG2(DBG_CFG, "   rand_bytes = %llu", data->lft.bytes.jitter);
+	DBG2(DBG_CFG, "   rekey_packets = %llu", data->lft.packets.rekey);
+	DBG2(DBG_CFG, "   life_packets = %llu", data->lft.packets.life);
+	DBG2(DBG_CFG, "   rand_packets = %llu", data->lft.packets.jitter);
+	DBG2(DBG_CFG, "   updown = %s", data->updown);
+	DBG2(DBG_CFG, "   hostaccess = %u", data->hostaccess);
+	DBG2(DBG_CFG, "   ipcomp = %u", data->ipcomp);
+	DBG2(DBG_CFG, "   mode = %N", ipsec_mode_names, data->mode);
+	if (data->replay_window != REPLAY_UNDEFINED)
+	{
+		DBG2(DBG_CFG, "   replay_window = %u", data->replay_window);
+	}
+	DBG2(DBG_CFG, "   dpd_action = %N", action_names, data->dpd_action);
+	DBG2(DBG_CFG, "   start_action = %N", action_names, data->start_action);
+	DBG2(DBG_CFG, "   close_action = %N", action_names, data->close_action);
+	DBG2(DBG_CFG, "   reqid = %u", data->reqid);
+	DBG2(DBG_CFG, "   tfc = %d", data->tfc);
+	DBG2(DBG_CFG, "   mark_in = %u/%u",
+		 data->mark_in.value, data->mark_in.mask);
+	DBG2(DBG_CFG, "   mark_out = %u/%u",
+		 data->mark_out.value, data->mark_out.mask);
+	DBG2(DBG_CFG, "   inactivity = %llu", data->inactivity);
+	DBG2(DBG_CFG, "   proposals = %#P", data->proposals);
+	DBG2(DBG_CFG, "   local_ts = %#R", data->local_ts);
+	DBG2(DBG_CFG, "   remote_ts = %#R", data->remote_ts);
+}
+
+/**
+ * Clean up CHILD config data
+ */
+static void free_child_data(child_data_t *data)
+{
+	data->proposals->destroy_offset(data->proposals,
+									offsetof(proposal_t, destroy));
+	data->local_ts->destroy_offset(data->local_ts,
+									offsetof(traffic_selector_t, destroy));
+	data->remote_ts->destroy_offset(data->remote_ts,
+									offsetof(traffic_selector_t, destroy));
+	free(data->updown);
+}
+
+/**
+ * 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)
+{
+	char buf[128];
+	proposal_t *proposal;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	if (strcaseeq("default", buf))
+	{
+		proposal = proposal_create_default(proto);
+		if (proposal)
+		{
+			list->insert_last(list, proposal);
+		}
+		proposal = proposal_create_default_aead(proto);
+		if (proposal)
+		{
+			list->insert_last(list, proposal);
+		}
+		return TRUE;
+	}
+	proposal = proposal_create_from_string(proto, buf);
+	if (proposal)
+	{
+		list->insert_last(list, proposal);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse IKE proposal
+ */
+CALLBACK(parse_ike_proposal, bool,
+	linked_list_t *out, chunk_t v)
+{
+	return parse_proposal(out, PROTO_IKE, v);
+}
+
+/**
+ * Parse ESP proposal
+ */
+CALLBACK(parse_esp_proposal, bool,
+	linked_list_t *out, chunk_t v)
+{
+	return parse_proposal(out, PROTO_ESP, v);
+}
+
+/**
+ * Parse AH proposal
+ */
+CALLBACK(parse_ah_proposal, bool,
+	linked_list_t *out, chunk_t v)
+{
+	return parse_proposal(out, PROTO_AH, v);
+}
+
+/**
+ * Parse a traffic selector
+ */
+CALLBACK(parse_ts, bool,
+	linked_list_t *out, chunk_t v)
+{
+	char buf[128], *protoport, *sep, *port = "", *end;
+	traffic_selector_t *ts;
+	struct protoent *protoent;
+	struct servent *svc;
+	long int p;
+	u_int16_t from = 0, to = 0xffff;
+	u_int8_t proto = 0;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+
+	protoport = strchr(buf, '[');
+	if (protoport)
+	{
+		*(protoport++) = '\0';
+
+		sep = strrchr(protoport, ']');
+		if (!sep)
+		{
+			return FALSE;
+		}
+		*sep = '\0';
+
+		sep = strchr(protoport, '/');
+		if (sep)
+		{	/* protocol/port */
+			*sep = '\0';
+			port = sep + 1;
+		}
+
+		if (streq(protoport, "any"))
+		{
+			proto = 0;
+		}
+		else
+		{
+			protoent = getprotobyname(protoport);
+			if (protoent)
+			{
+				proto = protoent->p_proto;
+			}
+			else
+			{
+				p = strtol(protoport, &end, 0);
+				if ((*protoport && *end) || p < 0 || p > 0xff)
+				{
+					return FALSE;
+				}
+				proto = (u_int8_t)p;
+			}
+		}
+		if (streq(port, "opaque"))
+		{
+			from = 0xffff;
+			to = 0;
+		}
+		else if (*port && !streq(port, "any"))
+		{
+			svc = getservbyname(port, NULL);
+			if (svc)
+			{
+				from = to = ntohs(svc->s_port);
+			}
+			else
+			{
+				p = strtol(port, &end, 0);
+				if (p < 0 || p > 0xffff)
+				{
+					return FALSE;
+				}
+				from = p;
+				if (*end == '-')
+				{
+					port = end + 1;
+					p = strtol(port, &end, 0);
+					if (p < 0 || p > 0xffff)
+					{
+						return FALSE;
+					}
+				}
+				to = p;
+				if (*end)
+				{
+					return FALSE;
+				}
+			}
+		}
+	}
+	if (streq(buf, "dynamic"))
+	{
+		ts = traffic_selector_create_dynamic(proto, from, to);
+	}
+	else
+	{
+		ts = traffic_selector_create_from_cidr(buf, proto, from, to);
+	}
+	if (!ts)
+	{
+		return FALSE;
+	}
+	out->insert_last(out, ts);
+	return TRUE;
+}
+
+/**
+ * Parse a string
+ */
+CALLBACK(parse_string, bool,
+	char **out, chunk_t v)
+{
+	if (!chunk_printable(v, NULL, ' '))
+	{
+		return FALSE;
+	}
+	free(*out);
+	*out = NULL;
+	if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
+	{
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Map a string to an integer
+ */
+typedef struct {
+	char *str;
+	int d;
+} enum_map_t;
+
+/**
+ * Parse a string to an integer mapping
+ */
+static bool parse_map(enum_map_t *map, int count, int *out, chunk_t v)
+{
+	char buf[128];
+	int i;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	for (i = 0; i < count; i++)
+	{
+		if (strcaseeq(map[i].str, buf))
+		{
+			*out = map[i].d;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Parse a boolean
+ */
+CALLBACK(parse_bool, bool,
+	bool *out, chunk_t v)
+{
+	enum_map_t map[] = {
+		{ "yes",		TRUE	},
+		{ "true",		TRUE	},
+		{ "enabled",	TRUE	},
+		{ "1",			TRUE	},
+		{ "no",			FALSE	},
+		{ "false",		FALSE	},
+		{ "disabled",	FALSE	},
+		{ "0",			FALSE	},
+	};
+	int d;
+
+	if (parse_map(map, countof(map), &d, v))
+	{
+		*out = d;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse a ipsec_mode_t
+ */
+CALLBACK(parse_mode, bool,
+	ipsec_mode_t *out, chunk_t v)
+{
+	enum_map_t map[] = {
+		{ "tunnel",		MODE_TUNNEL		},
+		{ "transport",	MODE_TRANSPORT	},
+		{ "beet",		MODE_BEET		},
+		{ "drop",		MODE_DROP		},
+		{ "pass",		MODE_PASS		},
+	};
+	int d;
+
+	if (parse_map(map, countof(map), &d, v))
+	{
+		*out = d;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse an action_t
+ */
+CALLBACK(parse_action, bool,
+	action_t *out, chunk_t v)
+{
+	enum_map_t map[] = {
+		{ "start",		ACTION_RESTART	},
+		{ "restart",	ACTION_RESTART	},
+		{ "route",		ACTION_ROUTE	},
+		{ "trap",		ACTION_ROUTE	},
+		{ "none",		ACTION_NONE		},
+		{ "clear",		ACTION_NONE		},
+	};
+	int d;
+
+	if (parse_map(map, countof(map), &d, v))
+	{
+		*out = d;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse a u_int32_t
+ */
+CALLBACK(parse_uint32, bool,
+	u_int32_t *out, chunk_t v)
+{
+	char buf[16], *end;
+	u_long l;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	l = strtoul(buf, &end, 0);
+	if (*end == 0)
+	{
+		*out = l;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse a u_int64_t
+ */
+CALLBACK(parse_uint64, bool,
+	u_int64_t *out, chunk_t v)
+{
+	char buf[16], *end;
+	unsigned long long l;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	l = strtoull(buf, &end, 0);
+	if (*end == 0)
+	{
+		*out = l;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse a relative time
+ */
+CALLBACK(parse_time, bool,
+	u_int64_t *out, chunk_t v)
+{
+	char buf[16], *end;
+	u_long l;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+
+	l = strtoul(buf, &end, 0);
+	while (*end == ' ')
+	{
+		end++;
+	}
+	switch (*end)
+	{
+		case 'd':
+		case 'D':
+			l *= 24;
+			/* fall */
+		case 'h':
+		case 'H':
+			l *= 60;
+			/* fall */
+		case 'm':
+		case 'M':
+			l *= 60;
+			/* fall */
+		case 's':
+		case 'S':
+			end++;
+			break;
+		case '\0':
+			break;
+		default:
+			return FALSE;
+	}
+	if (*end)
+	{
+		return FALSE;
+	}
+	*out = l;
+	return TRUE;
+}
+
+/**
+ * Parse byte volume
+ */
+CALLBACK(parse_bytes, bool,
+	u_int64_t *out, chunk_t v)
+{
+	char buf[16], *end;
+	unsigned long long l;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+
+	l = strtoull(buf, &end, 0);
+	while (*end == ' ')
+	{
+		end++;
+	}
+	switch (*end)
+	{
+		case 'g':
+		case 'G':
+			l *= 1024;
+			/* fall */
+		case 'm':
+		case 'M':
+			l *= 1024;
+			/* fall */
+		case 'k':
+		case 'K':
+			l *= 1024;
+			end++;
+			break;
+		case '\0':
+			break;
+		default:
+			return FALSE;
+	}
+	if (*end)
+	{
+		return FALSE;
+	}
+	*out = l;
+	return TRUE;
+}
+
+/**
+ * Parse a mark_t
+ */
+CALLBACK(parse_mark, bool,
+	mark_t *out, chunk_t v)
+{
+	char buf[32];
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	return mark_from_string(buf, out);
+}
+
+/**
+ * Parse TFC padding option
+ */
+CALLBACK(parse_tfc, bool,
+	u_int32_t *out, chunk_t v)
+{
+	if (chunk_equals(v, chunk_from_str("mtu")))
+	{
+		*out = -1;
+		return TRUE;
+	}
+	return parse_uint32(out, v);
+}
+
+/**
+ * Parse authentication config
+ */
+CALLBACK(parse_auth, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	char buf[64], *pos;
+	eap_vendor_type_t *type;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	if (strcaseeq(buf, "pubkey"))
+	{
+		cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+		return TRUE;
+	}
+	if (strcaseeq(buf, "psk"))
+	{
+		cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
+		return TRUE;
+	}
+	if (strcasepfx(buf, "xauth"))
+	{
+		pos = strchr(buf, '-');
+		if (pos)
+		{
+			cfg->add(cfg, AUTH_RULE_XAUTH_BACKEND, strdup(++pos));
+		}
+		cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_XAUTH);
+		return TRUE;
+	}
+	if (strcasepfx(buf, "eap"))
+	{
+		cfg->add(cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+
+		type = eap_vendor_type_from_string(buf);
+		if (type)
+		{
+			cfg->add(cfg, AUTH_RULE_EAP_TYPE, type->type);
+			if (type->vendor)
+			{
+				cfg->add(cfg, AUTH_RULE_EAP_VENDOR, type->vendor);
+			}
+			free(type);
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse identity; add as auth rule to config
+ */
+static bool parse_id(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
+{
+	char buf[256];
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	cfg->add(cfg, rule, identification_create_from_string(buf));
+	return TRUE;
+}
+
+/**
+ * Parse IKE identity
+ */
+CALLBACK(parse_ike_id, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	return parse_id(cfg, AUTH_RULE_IDENTITY, v);
+}
+
+/**
+ * Parse AAA identity
+ */
+CALLBACK(parse_aaa_id, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	return parse_id(cfg, AUTH_RULE_AAA_IDENTITY, v);
+}
+
+/**
+ * Parse EAP identity
+ */
+CALLBACK(parse_eap_id, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	return parse_id(cfg, AUTH_RULE_EAP_IDENTITY, v);
+}
+
+/**
+ * Parse XAuth identity
+ */
+CALLBACK(parse_xauth_id, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	return parse_id(cfg, AUTH_RULE_XAUTH_IDENTITY, v);
+}
+
+/**
+ * Parse group membership
+ */
+CALLBACK(parse_group, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	return parse_id(cfg, AUTH_RULE_GROUP, v);
+}
+
+/**
+ * Parse a certificate; add as auth rule to config
+ */
+static bool parse_cert(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
+{
+	certificate_t *cert;
+
+	cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+							  BUILD_BLOB_PEM, v, BUILD_END);
+	if (cert)
+	{
+		cfg->add(cfg, rule, cert);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse subject certificates
+ */
+CALLBACK(parse_certs, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	return parse_cert(cfg, AUTH_RULE_SUBJECT_CERT, v);
+}
+
+/**
+ * Parse CA certificates
+ */
+CALLBACK(parse_cacerts, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	return parse_cert(cfg, AUTH_RULE_CA_CERT, v);
+}
+
+/**
+ * Parse revocation status
+ */
+CALLBACK(parse_revocation, bool,
+	auth_cfg_t *cfg, chunk_t v)
+{
+	enum_map_t map[] = {
+		{ "strict",		VALIDATION_GOOD		},
+		{ "ifuri",		VALIDATION_SKIPPED	},
+		{ "relaxed",	VALIDATION_FAILED	},
+	};
+	int d;
+
+	if (parse_map(map, countof(map), &d, v))
+	{
+		if (d != VALIDATION_FAILED)
+		{
+			cfg->add(cfg, AUTH_RULE_CRL_VALIDATION, d);
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse list items to comma separated strings
+ */
+CALLBACK(parse_stringlist, bool,
+	char **out, chunk_t v)
+{
+	char *current;
+
+	if (!chunk_printable(v, NULL, ' '))
+	{
+		return FALSE;
+	}
+	current = *out;
+	if (current)
+	{
+		if (asprintf(out, "%s, %.*s", current, (int)v.len, v.ptr) == -1)
+		{
+			return FALSE;
+		}
+		free(current);
+	}
+	else
+	{
+		if (asprintf(out, "%.*s", (int)v.len, v.ptr) == -1)
+		{
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * Parse an fragmentation_t
+ */
+CALLBACK(parse_frag, bool,
+	fragmentation_t *out, chunk_t v)
+{
+	enum_map_t map[] = {
+		{ "yes",		FRAGMENTATION_YES		},
+		{ "no",			FRAGMENTATION_NO		},
+		{ "force",		FRAGMENTATION_FORCE		},
+	};
+	int d;
+
+	if (parse_map(map, countof(map), &d, v))
+	{
+		*out = d;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse a cert_policy_t
+ */
+CALLBACK(parse_send_cert, bool,
+	cert_policy_t *out, chunk_t v)
+{
+	enum_map_t map[] = {
+		{ "ifasked",	CERT_SEND_IF_ASKED	},
+		{ "always",		CERT_ALWAYS_SEND	},
+		{ "never",		CERT_NEVER_SEND		},
+	};
+	int d;
+
+	if (parse_map(map, countof(map), &d, v))
+	{
+		*out = d;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse a unique_policy_t
+ */
+CALLBACK(parse_unique, bool,
+	unique_policy_t *out, chunk_t v)
+{
+	enum_map_t map[] = {
+		{ "never",		UNIQUE_NEVER		},
+		{ "no",			UNIQUE_NO			},
+		{ "replace",	UNIQUE_REPLACE		},
+		{ "keep",		UNIQUE_KEEP			},
+	};
+	int d;
+
+	if (parse_map(map, countof(map), &d, v))
+	{
+		*out = d;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Parse host_t into a list
+ */
+CALLBACK(parse_hosts, bool,
+	linked_list_t *list, chunk_t v)
+{
+	char buf[64];
+	host_t *host;
+
+	if (!vici_stringify(v, buf, sizeof(buf)))
+	{
+		return FALSE;
+	}
+	host = host_create_from_string(buf, 0);
+	if (!host)
+	{
+		return FALSE;
+	}
+	list->insert_last(list, host);
+	return TRUE;
+}
+
+CALLBACK(child_li, bool,
+	child_data_t *child, vici_message_t *message, char *name, chunk_t value)
+{
+	parse_rule_t rules[] = {
+		{ "ah_proposals",	parse_ah_proposal,	child->proposals			},
+		{ "esp_proposals",	parse_esp_proposal,	child->proposals			},
+		{ "local_ts",		parse_ts,			child->local_ts				},
+		{ "remote_ts",		parse_ts,			child->remote_ts			},
+	};
+
+	return parse_rules(rules, countof(rules), name, value,
+					   &child->request->reply);
+}
+
+CALLBACK(child_kv, bool,
+	child_data_t *child, vici_message_t *message, char *name, chunk_t value)
+{
+	parse_rule_t rules[] = {
+		{ "updown",			parse_string,		&child->updown				},
+		{ "hostaccess",		parse_bool,			&child->hostaccess			},
+		{ "mode",			parse_mode,			&child->mode				},
+		{ "replay_window",	parse_uint32,		&child->replay_window		},
+		{ "rekey_time",		parse_time,			&child->lft.time.rekey		},
+		{ "life_time",		parse_time,			&child->lft.time.life		},
+		{ "rand_time",		parse_time,			&child->lft.time.jitter		},
+		{ "rekey_bytes",	parse_bytes,		&child->lft.bytes.rekey		},
+		{ "life_bytes",		parse_bytes,		&child->lft.bytes.life		},
+		{ "rand_bytes",		parse_bytes,		&child->lft.bytes.jitter	},
+		{ "rekey_packets",	parse_uint64,		&child->lft.packets.rekey	},
+		{ "life_packets",	parse_uint64,		&child->lft.packets.life	},
+		{ "rand_packets",	parse_uint64,		&child->lft.packets.jitter	},
+		{ "dpd_action",		parse_action,		&child->dpd_action			},
+		{ "start_action",	parse_action,		&child->start_action		},
+		{ "close_action",	parse_action,		&child->close_action		},
+		{ "ipcomp",			parse_bool,			&child->ipcomp				},
+		{ "inactivity",		parse_time,			&child->inactivity			},
+		{ "reqid",			parse_uint32,		&child->reqid				},
+		{ "mark_in",		parse_mark,			&child->mark_in				},
+		{ "mark_out",		parse_mark,			&child->mark_out			},
+		{ "tfc_padding",	parse_tfc,			&child->tfc					},
+	};
+
+	return parse_rules(rules, countof(rules), name, value,
+					   &child->request->reply);
+}
+
+CALLBACK(auth_li, bool,
+	auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
+{
+	parse_rule_t rules[] = {
+		{ "groups",			parse_group,		auth->cfg					},
+		{ "certs",			parse_certs,		auth->cfg					},
+		{ "cacerts",		parse_cacerts,		auth->cfg					},
+	};
+
+	return parse_rules(rules, countof(rules), name, value,
+					   &auth->request->reply);
+}
+
+CALLBACK(auth_kv, bool,
+	auth_data_t *auth, vici_message_t *message, char *name, chunk_t value)
+{
+	parse_rule_t rules[] = {
+		{ "auth",			parse_auth,			auth->cfg					},
+		{ "id",				parse_ike_id,		auth->cfg					},
+		{ "aaa_id",			parse_aaa_id,		auth->cfg					},
+		{ "eap_id",			parse_eap_id,		auth->cfg					},
+		{ "xauth_id",		parse_xauth_id,		auth->cfg					},
+		{ "revocation",		parse_revocation,	auth->cfg					},
+	};
+
+	return parse_rules(rules, countof(rules), name, value,
+					   &auth->request->reply);
+}
+
+CALLBACK(peer_li, bool,
+	peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
+{
+	parse_rule_t rules[] = {
+		{ "local_addrs",	parse_stringlist,	&peer->local_addrs			},
+		{ "remote_addrs",	parse_stringlist,	&peer->remote_addrs			},
+		{ "proposals",		parse_ike_proposal,	peer->proposals				},
+		{ "vips",			parse_hosts,		peer->vips					},
+		{ "pools",			parse_stringlist,	&peer->pools				},
+	};
+
+	return parse_rules(rules, countof(rules), name, value,
+					   &peer->request->reply);
+}
+
+CALLBACK(peer_kv, bool,
+	peer_data_t *peer, vici_message_t *message, char *name, chunk_t value)
+{
+	parse_rule_t rules[] = {
+		{ "version",		parse_uint32,		&peer->version				},
+		{ "aggressive",		parse_bool,			&peer->aggressive			},
+		{ "pull",			parse_bool,			&peer->pull					},
+		{ "encap",			parse_bool,			&peer->encap				},
+		{ "mobike",			parse_bool,			&peer->mobike				},
+		{ "dpd_delay",		parse_time,			&peer->dpd_delay			},
+		{ "dpd_timeout",	parse_time,			&peer->dpd_timeout			},
+		{ "fragmentation",	parse_frag,			&peer->fragmentation		},
+		{ "send_certreq",	parse_bool,			&peer->send_certreq			},
+		{ "send_cert",		parse_send_cert,	&peer->send_cert			},
+		{ "keyingtries",	parse_uint32,		&peer->keyingtries			},
+		{ "unique",			parse_unique,		&peer->unique				},
+		{ "local_port",		parse_uint32,		&peer->local_port			},
+		{ "remote_port",	parse_uint32,		&peer->remote_port			},
+		{ "reauth_time",	parse_time,			&peer->reauth_time			},
+		{ "rekey_time",		parse_time,			&peer->rekey_time			},
+		{ "over_time",		parse_time,			&peer->over_time			},
+		{ "rand_time",		parse_time,			&peer->rand_time			},
+	};
+
+	return parse_rules(rules, countof(rules), name, value,
+					   &peer->request->reply);
+}
+
+CALLBACK(children_sn, bool,
+	peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
+	char *name)
+{
+	child_data_t child = {
+		.request = peer->request,
+		.proposals = linked_list_create(),
+		.local_ts = linked_list_create(),
+		.remote_ts = linked_list_create(),
+		.mode = MODE_TUNNEL,
+		.replay_window = REPLAY_UNDEFINED,
+		.dpd_action = ACTION_NONE,
+		.start_action = ACTION_NONE,
+		.close_action = ACTION_NONE,
+		.lft = {
+			.time = {
+				.rekey = LFT_DEFAULT_CHILD_REKEY,
+				.life = LFT_UNDEFINED,
+				.jitter = LFT_UNDEFINED,
+			},
+			.bytes = {
+				.life = LFT_UNDEFINED,
+				.jitter = LFT_UNDEFINED,
+			},
+			.packets = {
+				.life = LFT_UNDEFINED,
+				.jitter = LFT_UNDEFINED,
+			},
+		}
+	};
+	child_cfg_t *cfg;
+	proposal_t *proposal;
+	traffic_selector_t *ts;
+
+	if (!message->parse(message, ctx, NULL, child_kv, child_li, &child))
+	{
+		free_child_data(&child);
+		return FALSE;
+	}
+
+	if (child.local_ts->get_count(child.local_ts) == 0)
+	{
+		child.local_ts->insert_last(child.local_ts,
+							traffic_selector_create_dynamic(0, 0, 65535));
+	}
+	if (child.remote_ts->get_count(child.remote_ts) == 0)
+	{
+		child.remote_ts->insert_last(child.remote_ts,
+							traffic_selector_create_dynamic(0, 0, 65535));
+	}
+	if (child.proposals->get_count(child.proposals) == 0)
+	{
+		proposal = proposal_create_default(PROTO_ESP);
+		if (proposal)
+		{
+			child.proposals->insert_last(child.proposals, proposal);
+		}
+		proposal = proposal_create_default_aead(PROTO_ESP);
+		if (proposal)
+		{
+			child.proposals->insert_last(child.proposals, proposal);
+		}
+	}
+
+	/* if no hard lifetime specified, add one at soft lifetime + 10% */
+	if (child.lft.time.life == LFT_UNDEFINED)
+	{
+		child.lft.time.life = child.lft.time.rekey * 110 / 100;
+	}
+	if (child.lft.bytes.life == LFT_UNDEFINED)
+	{
+		child.lft.bytes.life = child.lft.bytes.rekey * 110 / 100;
+	}
+	if (child.lft.packets.life == LFT_UNDEFINED)
+	{
+		child.lft.packets.life = child.lft.packets.rekey * 110 / 100;
+	}
+	/* if no rand time defined, use difference of hard and soft */
+	if (child.lft.time.jitter == LFT_UNDEFINED)
+	{
+		child.lft.time.jitter = child.lft.time.life -
+						min(child.lft.time.life, child.lft.time.rekey);
+	}
+	if (child.lft.bytes.jitter == LFT_UNDEFINED)
+	{
+		child.lft.bytes.jitter = child.lft.bytes.life -
+						min(child.lft.bytes.life, child.lft.bytes.rekey);
+	}
+	if (child.lft.packets.jitter == LFT_UNDEFINED)
+	{
+		child.lft.packets.jitter = child.lft.packets.life -
+						min(child.lft.packets.life, child.lft.packets.rekey);
+	}
+
+	log_child_data(&child, name);
+
+	cfg = child_cfg_create(name, &child.lft, child.updown,
+						child.hostaccess, child.mode, child.start_action,
+						child.dpd_action, child.close_action, child.ipcomp,
+						child.inactivity, child.reqid, &child.mark_in,
+						&child.mark_out, child.tfc);
+
+	if (child.replay_window != REPLAY_UNDEFINED)
+	{
+		cfg->set_replay_window(cfg, child.replay_window);
+	}
+	while (child.local_ts->remove_first(child.local_ts,
+										(void**)&ts) == SUCCESS)
+	{
+		cfg->add_traffic_selector(cfg, TRUE, ts);
+	}
+	while (child.remote_ts->remove_first(child.remote_ts,
+										 (void**)&ts) == SUCCESS)
+	{
+		cfg->add_traffic_selector(cfg, FALSE, ts);
+	}
+	while (child.proposals->remove_first(child.proposals,
+										 (void**)&proposal) == SUCCESS)
+	{
+		cfg->add_proposal(cfg, proposal);
+	}
+
+	peer->children->insert_last(peer->children, cfg);
+
+	free_child_data(&child);
+
+	return TRUE;
+}
+
+CALLBACK(peer_sn, bool,
+	peer_data_t *peer, vici_message_t *message, vici_parse_context_t *ctx,
+	char *name)
+{
+	if (strcaseeq(name, "children"))
+	{
+		return message->parse(message, ctx, children_sn, NULL, NULL, peer);
+	}
+	if (strcasepfx(name, "local") ||
+		strcasepfx(name, "remote"))
+	{
+		auth_data_t auth = {
+			.request = peer->request,
+			.cfg = auth_cfg_create(),
+		};
+
+		if (!message->parse(message, ctx, NULL, auth_kv, auth_li, &auth))
+		{
+			auth.cfg->destroy(auth.cfg);
+			return FALSE;
+		}
+
+		if (strcasepfx(name, "local"))
+		{
+			peer->local->insert_last(peer->local, auth.cfg);
+		}
+		else
+		{
+			peer->remote->insert_last(peer->remote, auth.cfg);
+		}
+		return TRUE;
+	}
+	peer->request->reply = create_reply("invalid section: %s", name);
+	return FALSE;
+}
+
+/**
+ * Find reqid of an existing CHILD_SA
+ */
+static u_int32_t find_reqid(child_cfg_t *cfg)
+{
+	enumerator_t *enumerator, *children;
+	child_sa_t *child_sa;
+	ike_sa_t *ike_sa;
+	u_int32_t reqid;
+
+	reqid = charon->traps->find_reqid(charon->traps, cfg);
+	if (reqid)
+	{	/* already trapped */
+		return reqid;
+	}
+
+	enumerator = charon->controller->create_ike_sa_enumerator(
+													charon->controller, TRUE);
+	while (!reqid && enumerator->enumerate(enumerator, &ike_sa))
+	{
+		children = ike_sa->create_child_sa_enumerator(ike_sa);
+		while (children->enumerate(children, &child_sa))
+		{
+			if (streq(cfg->get_name(cfg), child_sa->get_name(child_sa)))
+			{
+				reqid = child_sa->get_reqid(child_sa);
+				break;
+			}
+		}
+		children->destroy(children);
+	}
+	enumerator->destroy(enumerator);
+	return reqid;
+}
+
+/**
+ * Perform start actions associated to a child config
+ */
+static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
+							 child_cfg_t *child_cfg)
+{
+	switch (child_cfg->get_start_action(child_cfg))
+	{
+		case ACTION_RESTART:
+			DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
+			charon->controller->initiate(charon->controller,
+					peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
+					NULL, NULL, 0);
+			break;
+		case ACTION_ROUTE:
+			DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
+			switch (child_cfg->get_mode(child_cfg))
+			{
+				case MODE_PASS:
+				case MODE_DROP:
+					charon->shunts->install(charon->shunts, child_cfg);
+					break;
+				default:
+					charon->traps->install(charon->traps, peer_cfg, child_cfg,
+										   find_reqid(child_cfg));
+					break;
+			}
+			break;
+		default:
+			break;
+	}
+}
+
+/**
+ * Undo start actions associated to a child config
+ */
+static void clear_start_action(private_vici_config_t *this,
+							   child_cfg_t *child_cfg)
+{
+	enumerator_t *enumerator, *children;
+	child_sa_t *child_sa;
+	ike_sa_t *ike_sa;
+	u_int32_t reqid = 0, *del;
+	array_t *reqids = NULL;
+	char *name;
+
+	name = child_cfg->get_name(child_cfg);
+	switch (child_cfg->get_start_action(child_cfg))
+	{
+		case ACTION_RESTART:
+			enumerator = charon->controller->create_ike_sa_enumerator(
+													charon->controller, TRUE);
+			while (enumerator->enumerate(enumerator, &ike_sa))
+			{
+				children = ike_sa->create_child_sa_enumerator(ike_sa);
+				while (children->enumerate(children, &child_sa))
+				{
+					if (streq(name, child_sa->get_name(child_sa)))
+					{
+						reqid = child_sa->get_reqid(child_sa);
+						array_insert_create(&reqids, ARRAY_TAIL, &reqid);
+					}
+				}
+				children->destroy(children);
+			}
+			enumerator->destroy(enumerator);
+
+			if (array_count(reqids))
+			{
+				while (array_remove(reqids, ARRAY_HEAD, &del))
+				{
+					DBG1(DBG_CFG, "closing '%s' #%u", name, *del);
+					charon->controller->terminate_child(charon->controller,
+														*del, NULL, NULL, 0);
+				}
+				array_destroy(reqids);
+			}
+			break;
+		case ACTION_ROUTE:
+			DBG1(DBG_CFG, "uninstalling '%s'", name);
+			switch (child_cfg->get_mode(child_cfg))
+			{
+				case MODE_PASS:
+				case MODE_DROP:
+					charon->shunts->uninstall(charon->shunts, name);
+					break;
+				default:
+					enumerator = charon->traps->create_enumerator(charon->traps);
+					while (enumerator->enumerate(enumerator, NULL, &child_sa))
+					{
+						if (streq(name, child_sa->get_name(child_sa)))
+						{
+							reqid = child_sa->get_reqid(child_sa);
+							break;
+						}
+					}
+					enumerator->destroy(enumerator);
+					if (reqid)
+					{
+						charon->traps->uninstall(charon->traps, reqid);
+					}
+					break;
+			}
+			break;
+		default:
+			break;
+	}
+}
+
+/**
+ * Run start actions associated to all child configs of a peer config
+ */
+static void run_start_actions(private_vici_config_t *this, peer_cfg_t *peer_cfg)
+{
+	enumerator_t *enumerator;
+	child_cfg_t *child_cfg;
+
+	enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+	while (enumerator->enumerate(enumerator, &child_cfg))
+	{
+		run_start_action(this, peer_cfg, child_cfg);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Undo start actions associated to all child configs of a peer config
+ */
+static void clear_start_actions(private_vici_config_t *this,
+								peer_cfg_t *peer_cfg)
+{
+	enumerator_t *enumerator;
+	child_cfg_t *child_cfg;
+
+	enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+	while (enumerator->enumerate(enumerator, &child_cfg))
+	{
+		clear_start_action(this, child_cfg);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Replace children of a peer config by a new config
+ */
+static void replace_children(private_vici_config_t *this,
+							 peer_cfg_t *from, peer_cfg_t *to)
+{
+	enumerator_t *enumerator;
+	child_cfg_t *child;
+
+	enumerator = to->create_child_cfg_enumerator(to);
+	while (enumerator->enumerate(enumerator, &child))
+	{
+		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);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Merge/replace a peer config with existing configs
+ */
+static void merge_config(private_vici_config_t *this, peer_cfg_t *peer_cfg)
+{
+	enumerator_t *enumerator;
+	peer_cfg_t *current;
+	ike_cfg_t *ike_cfg;
+	bool merged = FALSE;
+
+	this->lock->write_lock(this->lock);
+
+	enumerator = this->conns->create_enumerator(this->conns);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (streq(peer_cfg->get_name(peer_cfg), current->get_name(current)))
+		{
+			ike_cfg = current->get_ike_cfg(current);
+			if (peer_cfg->equals(peer_cfg, current) &&
+				ike_cfg->equals(ike_cfg, peer_cfg->get_ike_cfg(peer_cfg)))
+			{
+				DBG1(DBG_CFG, "updated vici connection: %s",
+					 peer_cfg->get_name(peer_cfg));
+				replace_children(this, peer_cfg, current);
+				peer_cfg->destroy(peer_cfg);
+			}
+			else
+			{
+				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);
+			}
+			merged = TRUE;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	if (!merged)
+	{
+		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);
+	}
+
+	this->lock->unlock(this->lock);
+}
+
+CALLBACK(config_sn, bool,
+	request_data_t *request, vici_message_t *message,
+	vici_parse_context_t *ctx, char *name)
+{
+	peer_data_t peer = {
+		.request = request,
+		.local = linked_list_create(),
+		.remote = linked_list_create(),
+		.vips = linked_list_create(),
+		.children = linked_list_create(),
+		.proposals = linked_list_create(),
+		.mobike = TRUE,
+		.send_certreq = TRUE,
+		.pull = TRUE,
+		.send_cert = CERT_SEND_IF_ASKED,
+		.version = IKE_ANY,
+		.remote_port = IKEV2_UDP_PORT,
+		.fragmentation = FRAGMENTATION_NO,
+		.unique = UNIQUE_NO,
+		.keyingtries = 1,
+		.rekey_time = LFT_DEFAULT_IKE_REKEY,
+		.over_time = LFT_UNDEFINED,
+		.rand_time = LFT_UNDEFINED,
+	};
+	enumerator_t *enumerator;
+	peer_cfg_t *peer_cfg;
+	ike_cfg_t *ike_cfg;
+	child_cfg_t *child_cfg;
+	auth_cfg_t *auth_cfg;
+	proposal_t *proposal;
+	host_t *host;
+	char *str;
+
+	DBG2(DBG_CFG, " conn %s:", name);
+
+	if (!message->parse(message, ctx, peer_sn, peer_kv, peer_li, &peer))
+	{
+		free_peer_data(&peer);
+		return FALSE;
+	}
+
+	if (peer.local->get_count(peer.local) == 0)
+	{
+		free_peer_data(&peer);
+		peer.request->reply = create_reply("missing local auth config");
+		return FALSE;
+	}
+	if (peer.remote->get_count(peer.remote) == 0)
+	{
+		auth_cfg = auth_cfg_create();
+		peer.remote->insert_last(peer.remote, auth_cfg);
+	}
+	if (peer.proposals->get_count(peer.proposals) == 0)
+	{
+		proposal = proposal_create_default(PROTO_IKE);
+		if (proposal)
+		{
+			peer.proposals->insert_last(peer.proposals, proposal);
+		}
+		proposal = proposal_create_default_aead(PROTO_IKE);
+		if (proposal)
+		{
+			peer.proposals->insert_last(peer.proposals, proposal);
+		}
+	}
+	if (!peer.local_addrs)
+	{
+		peer.local_addrs = strdup("%any");
+	}
+	if (!peer.remote_addrs)
+	{
+		peer.remote_addrs = strdup("%any");
+	}
+	if (!peer.local_port)
+	{
+		peer.local_port = charon->socket->get_port(charon->socket, FALSE);
+	}
+
+	if (peer.over_time == LFT_UNDEFINED)
+	{
+		/* default over_time to 10% of rekey/reauth time if not given */
+		peer.over_time = max(peer.rekey_time, peer.reauth_time) / 10;
+	}
+	if (peer.rand_time == LFT_UNDEFINED)
+	{
+		/* default rand_time to over_time if not given */
+		peer.rand_time = min(peer.over_time,
+							 max(peer.rekey_time, peer.reauth_time) / 2);
+	}
+
+	log_peer_data(&peer);
+
+	ike_cfg = ike_cfg_create(peer.version, peer.send_certreq, peer.encap,
+						peer.local_addrs, peer.local_port,
+						peer.remote_addrs, peer.remote_port,
+						peer.fragmentation, 0);
+	peer_cfg = peer_cfg_create(name, ike_cfg, peer.send_cert, peer.unique,
+						peer.keyingtries, peer.rekey_time, peer.reauth_time,
+						peer.rand_time, peer.over_time, peer.mobike,
+						peer.aggressive, peer.pull,
+						peer.dpd_delay, peer.dpd_timeout,
+						FALSE, NULL, NULL);
+
+	while (peer.local->remove_first(peer.local,
+									(void**)&auth_cfg) == SUCCESS)
+	{
+		peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE);
+	}
+	while (peer.remote->remove_first(peer.remote,
+									 (void**)&auth_cfg) == SUCCESS)
+	{
+		peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
+	}
+	while (peer.children->remove_first(peer.children,
+									   (void**)&child_cfg) == SUCCESS)
+	{
+		peer_cfg->add_child_cfg(peer_cfg, child_cfg);
+	}
+	while (peer.proposals->remove_first(peer.proposals,
+										(void**)&proposal) == SUCCESS)
+	{
+		ike_cfg->add_proposal(ike_cfg, proposal);
+	}
+	while (peer.vips->remove_first(peer.vips, (void**)&host) == SUCCESS)
+	{
+		peer_cfg->add_virtual_ip(peer_cfg, host);
+	}
+	if (peer.pools)
+	{
+		enumerator = enumerator_create_token(peer.pools, ",", " ");
+		while (enumerator->enumerate(enumerator, &str))
+		{
+			peer_cfg->add_pool(peer_cfg, str);
+		}
+		enumerator->destroy(enumerator);
+	}
+
+	free_peer_data(&peer);
+
+	merge_config(request->this, peer_cfg);
+
+	return TRUE;
+}
+
+CALLBACK(load_conn, vici_message_t*,
+	private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
+{
+	request_data_t request = {
+		.this = this,
+	};
+
+	if (!message->parse(message, NULL, config_sn, NULL, NULL, &request))
+	{
+		if (request.reply)
+		{
+			return request.reply;
+		}
+		return create_reply("parsing request failed");
+	}
+	return create_reply(NULL);
+}
+
+CALLBACK(unload_conn, vici_message_t*,
+	private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
+{
+	enumerator_t *enumerator;
+	peer_cfg_t *cfg;
+	bool found = FALSE;
+	char *conn;
+
+	conn = message->get_str(message, NULL, "name");
+	if (!conn)
+	{
+		return create_reply("missing connection name to unload");
+	}
+
+	this->lock->write_lock(this->lock);
+	enumerator = this->conns->create_enumerator(this->conns);
+	while (enumerator->enumerate(enumerator, &cfg))
+	{
+		if (streq(cfg->get_name(cfg), conn))
+		{
+			this->conns->remove_at(this->conns, enumerator);
+			cfg->destroy(cfg);
+			found = TRUE;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->lock->unlock(this->lock);
+
+	if (!found)
+	{
+		return create_reply("connection '%s' not found for unloading", conn);
+	}
+	return create_reply(NULL);
+}
+
+CALLBACK(get_conns, vici_message_t*,
+	private_vici_config_t *this, char *name, u_int id, vici_message_t *message)
+{
+	vici_builder_t *builder;
+	enumerator_t *enumerator;
+	peer_cfg_t *cfg;
+
+	builder = vici_builder_create();
+	builder->begin_list(builder, "conns");
+
+	this->lock->read_lock(this->lock);
+	enumerator = this->conns->create_enumerator(this->conns);
+	while (enumerator->enumerate(enumerator, &cfg))
+	{
+		builder->add_li(builder, "%s", cfg->get_name(cfg));
+	}
+	enumerator->destroy(enumerator);
+	this->lock->unlock(this->lock);
+
+	builder->end_list(builder);
+
+	return builder->finalize(builder);
+}
+
+static void manage_command(private_vici_config_t *this,
+						   char *name, vici_command_cb_t cb, bool reg)
+{
+	this->dispatcher->manage_command(this->dispatcher, name,
+									 reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_config_t *this, bool reg)
+{
+	manage_command(this, "load-conn", load_conn, reg);
+	manage_command(this, "unload-conn", unload_conn, reg);
+	manage_command(this, "get-conns", get_conns, reg);
+}
+
+METHOD(vici_config_t, destroy, void,
+	private_vici_config_t *this)
+{
+	manage_commands(this, FALSE);
+	this->conns->destroy_offset(this->conns, offsetof(peer_cfg_t, destroy));
+	this->lock->destroy(this->lock);
+	free(this);
+}
+
+/**
+ * See header
+ */
+vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher)
+{
+	private_vici_config_t *this;
+
+	INIT(this,
+		.public = {
+			.backend = {
+				.create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
+				.create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
+				.get_peer_cfg_by_name = _get_peer_cfg_by_name,
+			},
+			.destroy = _destroy,
+		},
+		.dispatcher = dispatcher,
+		.conns = linked_list_create(),
+		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+	);
+
+	manage_commands(this, TRUE);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_config.h b/src/libcharon/plugins/vici/vici_config.h
new file mode 100644
index 0000000..820d5f3
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_config.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup vici_config vici_config
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_CONFIG_H_
+#define VICI_CONFIG_H_
+
+#include "vici_dispatcher.h"
+
+#include <config/backend.h>
+
+typedef struct vici_config_t vici_config_t;
+
+/**
+ * In-memory configuration backend, managed by VICI.
+ */
+struct vici_config_t {
+
+	/**
+	 * Implements a configuraiton backend.
+	 */
+	backend_t backend;
+
+	/**
+	 * Destroy a vici_config_t.
+	 */
+	void (*destroy)(vici_config_t *this);
+};
+/**
+ * Create a vici_config instance.
+ *
+ * @param dispatcher		dispatcher to receive requests from
+ * @return					config backend
+ */
+vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
new file mode 100644
index 0000000..3cd0081
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -0,0 +1,496 @@
+/*
+ * 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 "vici_control.h"
+#include "vici_builder.h"
+
+#include <inttypes.h>
+
+#include <daemon.h>
+#include <collections/array.h>
+
+typedef struct private_vici_control_t private_vici_control_t;
+
+/**
+ * Private data of an vici_control_t object.
+ */
+struct private_vici_control_t {
+
+	/**
+	 * Public vici_control_t interface.
+	 */
+	vici_control_t public;
+
+	/**
+	 * Dispatcher
+	 */
+	vici_dispatcher_t *dispatcher;
+};
+
+/**
+ * Log callback helper data
+ */
+typedef struct {
+	/** dispatcher to send log messages over */
+	vici_dispatcher_t *dispatcher;
+	/** connection ID to send messages to */
+	u_int id;
+	/** loglevel */
+	level_t level;
+	/** prevent recursive log */
+	u_int recursive;
+} log_info_t;
+
+/**
+ * Log using vici event messages
+ */
+static bool log_vici(log_info_t *info, debug_t group, level_t level,
+					 ike_sa_t *ike_sa, char *text)
+{
+	if (level <= info->level)
+	{
+		if (info->recursive++ == 0)
+		{
+			vici_message_t *message;
+			vici_builder_t *builder;
+
+			builder = vici_builder_create();
+			builder->add_kv(builder, "group", "%N", debug_names, group);
+			builder->add_kv(builder, "level", "%d", level);
+			if (ike_sa)
+			{
+				builder->add_kv(builder, "ikesa-name", "%s",
+								ike_sa->get_name(ike_sa));
+				builder->add_kv(builder, "ikesa-uniqueid", "%u",
+								ike_sa->get_unique_id(ike_sa));
+			}
+			builder->add_kv(builder, "msg", "%s", text);
+
+			message = builder->finalize(builder);
+			if (message)
+			{
+				info->dispatcher->raise_event(info->dispatcher, "control-log",
+											  info->id, message);
+			}
+		}
+		info->recursive--;
+	}
+	return TRUE;
+}
+
+/**
+ * Send a (error) reply message
+ */
+static vici_message_t* send_reply(private_vici_control_t *this, char *fmt, ...)
+{
+	vici_builder_t *builder;
+	va_list args;
+
+	builder = vici_builder_create();
+	builder->add_kv(builder, "success", fmt ? "no" : "yes");
+	if (fmt)
+	{
+		va_start(args, fmt);
+		builder->vadd_kv(builder, "errmsg", fmt, args);
+		va_end(args);
+	}
+	return builder->finalize(builder);
+}
+
+/**
+ * Get the child_cfg having name from peer_cfg
+ */
+static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
+{
+	child_cfg_t *current, *found = NULL;
+	enumerator_t *enumerator;
+
+	enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (streq(current->get_name(current), name))
+		{
+			found = current;
+			found->get_ref(found);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	return found;
+}
+
+/**
+ * Find a peer/child config from a child config name
+ */
+static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
+{
+	enumerator_t *enumerator;
+	peer_cfg_t *peer_cfg;
+	child_cfg_t *child_cfg;
+
+	enumerator = charon->backends->create_peer_cfg_enumerator(
+							charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
+	while (enumerator->enumerate(enumerator, &peer_cfg))
+	{
+		child_cfg = get_child_from_peer(peer_cfg, name);
+		if (child_cfg)
+		{
+			*out = peer_cfg->get_ref(peer_cfg);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	return child_cfg;
+}
+
+CALLBACK(initiate, vici_message_t*,
+	private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+	child_cfg_t *child_cfg = NULL;
+	peer_cfg_t *peer_cfg;
+	char *child;
+	u_int timeout;
+	log_info_t log = {
+		.dispatcher = this->dispatcher,
+		.id = id,
+	};
+
+	child = request->get_str(request, NULL, "child");
+	timeout = request->get_int(request, 0, "timeout");
+	log.level = request->get_int(request, 1, "loglevel");
+
+	if (!child)
+	{
+		return send_reply(this, "missing configuration name");
+	}
+
+	DBG1(DBG_CFG, "vici initiate '%s'", child);
+
+	child_cfg = find_child_cfg(child, &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))
+	{
+		case SUCCESS:
+			return send_reply(this, NULL);
+		case OUT_OF_RES:
+			return send_reply(this, "CHILD_SA '%s' not established after %dms",
+							  child, timeout);
+		case FAILED:
+		default:
+			return send_reply(this, "establishing CHILD_SA '%s' failed", child);
+	}
+}
+
+CALLBACK(terminate, vici_message_t*,
+	private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+	enumerator_t *enumerator, *isas, *csas;
+	char *child, *ike, *errmsg = NULL;
+	u_int timeout, child_id, ike_id, current, *del, done = 0;
+	ike_sa_t *ike_sa;
+	child_sa_t *child_sa;
+	array_t *ids;
+	vici_builder_t *builder;
+	log_info_t log = {
+		.dispatcher = this->dispatcher,
+		.id = id,
+	};
+
+	child = request->get_str(request, NULL, "child");
+	ike = request->get_str(request, NULL, "ike");
+	child_id = request->get_int(request, 0, "child-id");
+	ike_id = request->get_int(request, 0, "ike-id");
+	timeout = request->get_int(request, 0, "timeout");
+	log.level = request->get_int(request, 1, "loglevel");
+
+	if (!child && !ike && !ike_id && !child_id)
+	{
+		return send_reply(this, "missing terminate selector");
+	}
+
+	if (ike_id)
+	{
+		DBG1(DBG_CFG, "vici terminate IKE_SA #%d", ike_id);
+	}
+	if (child_id)
+	{
+		DBG1(DBG_CFG, "vici terminate CHILD_SA #%d", child_id);
+	}
+	if (ike)
+	{
+		DBG1(DBG_CFG, "vici terminate IKE_SA '%s'", ike);
+	}
+	if (child)
+	{
+		DBG1(DBG_CFG, "vici terminate CHILD_SA '%s'", child);
+	}
+
+	ids = array_create(sizeof(u_int), 0);
+
+	isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
+	while (isas->enumerate(isas, &ike_sa))
+	{
+		if (child || child_id)
+		{
+			if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
+			{
+				continue;
+			}
+			if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
+			{
+				continue;
+			}
+			csas = ike_sa->create_child_sa_enumerator(ike_sa);
+			while (csas->enumerate(csas, &child_sa))
+			{
+				if (child && !streq(child, child_sa->get_name(child_sa)))
+				{
+					continue;
+				}
+				if (child_id && child_sa->get_reqid(child_sa) != child_id)
+				{
+					continue;
+				}
+				current = child_sa->get_reqid(child_sa);
+				array_insert(ids, ARRAY_TAIL, &current);
+			}
+			csas->destroy(csas);
+		}
+		else if (ike && streq(ike, ike_sa->get_name(ike_sa)))
+		{
+			current = ike_sa->get_unique_id(ike_sa);
+			array_insert(ids, ARRAY_TAIL, &current);
+		}
+		else if (ike_id && ike_id == ike_sa->get_unique_id(ike_sa))
+		{
+			array_insert(ids, ARRAY_TAIL, &ike_id);
+		}
+	}
+	isas->destroy(isas);
+
+	enumerator = array_create_enumerator(ids);
+	while (enumerator->enumerate(enumerator, &del))
+	{
+		if (child || child_id)
+		{
+			if (charon->controller->terminate_child(charon->controller, *del,
+						(controller_cb_t)log_vici, &log, timeout) == SUCCESS)
+			{
+				done++;
+			}
+		}
+		else
+		{
+			if (charon->controller->terminate_ike(charon->controller, *del,
+						(controller_cb_t)log_vici, &log, timeout) == SUCCESS)
+			{
+				done++;
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	builder = vici_builder_create();
+	if (array_count(ids) == 0)
+	{
+		errmsg = "no matching SAs to terminate found";
+	}
+	else if (done < array_count(ids))
+	{
+		if (array_count(ids) == 1)
+		{
+			errmsg = "terminating SA failed";
+		}
+		else
+		{
+			errmsg = "not all matching SAs could be terminated";
+		}
+	}
+	builder->add_kv(builder, "success", errmsg ? "no" : "yes");
+	builder->add_kv(builder, "matches", "%u", array_count(ids));
+	builder->add_kv(builder, "terminated", "%u", done);
+	if (errmsg)
+	{
+		builder->add_kv(builder, "errmsg", "%s", errmsg);
+	}
+	array_destroy(ids);
+	return builder->finalize(builder);
+}
+
+/**
+ * Find reqid of an existing CHILD_SA
+ */
+static u_int32_t find_reqid(child_cfg_t *cfg)
+{
+	enumerator_t *enumerator, *children;
+	child_sa_t *child_sa;
+	ike_sa_t *ike_sa;
+	u_int32_t reqid;
+
+	reqid = charon->traps->find_reqid(charon->traps, cfg);
+	if (reqid)
+	{	/* already trapped */
+		return reqid;
+	}
+
+	enumerator = charon->controller->create_ike_sa_enumerator(
+													charon->controller, TRUE);
+	while (!reqid && enumerator->enumerate(enumerator, &ike_sa))
+	{
+		children = ike_sa->create_child_sa_enumerator(ike_sa);
+		while (children->enumerate(children, &child_sa))
+		{
+			if (streq(cfg->get_name(cfg), child_sa->get_name(child_sa)))
+			{
+				reqid = child_sa->get_reqid(child_sa);
+				break;
+			}
+		}
+		children->destroy(children);
+	}
+	enumerator->destroy(enumerator);
+	return reqid;
+}
+
+CALLBACK(install, vici_message_t*,
+	private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+	child_cfg_t *child_cfg = NULL;
+	peer_cfg_t *peer_cfg;
+	char *child;
+	bool ok;
+
+	child = request->get_str(request, NULL, "child");
+	if (!child)
+	{
+		return send_reply(this, "missing configuration name");
+	}
+
+	DBG1(DBG_CFG, "vici install '%s'", child);
+
+	child_cfg = find_child_cfg(child, &peer_cfg);
+	if (!child_cfg)
+	{
+		return send_reply(this, "configuration name not found");
+	}
+	switch (child_cfg->get_mode(child_cfg))
+	{
+		case MODE_PASS:
+		case MODE_DROP:
+			ok = charon->shunts->install(charon->shunts, child_cfg);
+			break;
+		default:
+			ok = charon->traps->install(charon->traps, peer_cfg, child_cfg,
+										find_reqid(child_cfg));
+			break;
+	}
+	peer_cfg->destroy(peer_cfg);
+	child_cfg->destroy(child_cfg);
+
+	return send_reply(this, ok ? NULL : "installing policy '%s' failed", child);
+}
+
+CALLBACK(uninstall, vici_message_t*,
+	private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
+{
+	child_sa_t *child_sa;
+	enumerator_t *enumerator;
+	u_int32_t reqid = 0;
+	char *child;
+
+	child = request->get_str(request, NULL, "child");
+	if (!child)
+	{
+		return send_reply(this, "missing configuration name");
+	}
+
+	DBG1(DBG_CFG, "vici uninstall '%s'", child);
+
+	if (charon->shunts->uninstall(charon->shunts, child))
+	{
+		return send_reply(this, NULL);
+	}
+
+	enumerator = charon->traps->create_enumerator(charon->traps);
+	while (enumerator->enumerate(enumerator, NULL, &child_sa))
+	{
+		if (streq(child, child_sa->get_name(child_sa)))
+		{
+			reqid = child_sa->get_reqid(child_sa);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	if (reqid)
+	{
+		if (charon->traps->uninstall(charon->traps, reqid))
+		{
+			return send_reply(this, NULL);
+		}
+		return send_reply(this, "uninstalling policy '%s' failed", child);
+	}
+	return send_reply(this, "policy '%s' not found", child);
+}
+
+static void manage_command(private_vici_control_t *this,
+						   char *name, vici_command_cb_t cb, bool reg)
+{
+	this->dispatcher->manage_command(this->dispatcher, name,
+									 reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+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, "install", install, reg);
+	manage_command(this, "uninstall", uninstall, reg);
+	this->dispatcher->manage_event(this->dispatcher, "control-log", reg);
+}
+
+METHOD(vici_control_t, destroy, void,
+	private_vici_control_t *this)
+{
+	manage_commands(this, FALSE);
+	free(this);
+}
+
+/**
+ * See header
+ */
+vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher)
+{
+	private_vici_control_t *this;
+
+	INIT(this,
+		.public = {
+			.destroy = _destroy,
+		},
+		.dispatcher = dispatcher,
+	);
+
+	manage_commands(this, TRUE);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_control.h b/src/libcharon/plugins/vici/vici_control.h
new file mode 100644
index 0000000..71a13a0
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_control.h
@@ -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.
+ */
+
+/**
+ * @defgroup vici_control vici_control
+ * @{ @ingroup vici
+ */
+
+#include "vici_dispatcher.h"
+
+#ifndef VICI_CONTROL_H_
+#define VICI_CONTROL_H_
+
+typedef struct vici_control_t vici_control_t;
+
+/**
+ * Control helper, provides initiate/terminate and other commands.
+ */
+struct vici_control_t {
+
+	/**
+	 * Destroy a vici_control_t.
+	 */
+	void (*destroy)(vici_control_t *this);
+};
+
+/**
+ * Create a vici_control instance.
+ *
+ * @param dispatcher		dispatcher to receive requests from
+ * @return					query handler
+ */
+vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_CONTROL_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c
new file mode 100644
index 0000000..cc6434b
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cred.c
@@ -0,0 +1,330 @@
+/*
+ * 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 "vici_cred.h"
+#include "vici_builder.h"
+
+#include <credentials/sets/mem_cred.h>
+#include <credentials/certificates/ac.h>
+#include <credentials/certificates/crl.h>
+#include <credentials/certificates/x509.h>
+
+typedef struct private_vici_cred_t private_vici_cred_t;
+
+/**
+ * Private data of an vici_cred_t object.
+ */
+struct private_vici_cred_t {
+
+	/**
+	 * Public vici_cred_t interface.
+	 */
+	vici_cred_t public;
+
+	/**
+	 * Dispatcher
+	 */
+	vici_dispatcher_t *dispatcher;
+
+	/**
+	 * credentials
+	 */
+	mem_cred_t *creds;
+};
+
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+	vici_builder_t *builder;
+	va_list args;
+
+	builder = vici_builder_create();
+	builder->add_kv(builder, "success", fmt ? "no" : "yes");
+	if (fmt)
+	{
+		va_start(args, fmt);
+		builder->vadd_kv(builder, "errmsg", fmt, args);
+		va_end(args);
+	}
+	return builder->finalize(builder);
+}
+
+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;
+	x509_t *x509;
+	chunk_t data;
+	char *str;
+
+	str = message->get_str(message, NULL, "type");
+	if (!str)
+	{
+		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"))
+	{
+		type = CERT_X509_CRL;
+	}
+	else if (strcaseeq(str, "x509ac"))
+	{
+		type = CERT_X509_AC;
+	}
+	else
+	{
+		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");
+	}
+	cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
+							  BUILD_BLOB_PEM, data,
+							  BUILD_X509_FLAG, additional_flags,
+							  BUILD_END);
+	if (!cert)
+	{
+		return create_reply("parsing %N certificate failed",
+							certificate_type_names, type);
+	}
+	if (cert->get_type(cert) == CERT_X509)
+	{
+		x509 = (x509_t*)cert;
+
+		if ((required_flags & x509->get_flags(x509)) != required_flags)
+		{
+			cert->destroy(cert);
+			return create_reply("certificate misses required flag, rejected");
+		}
+	}
+
+	DBG1(DBG_CFG, "loaded certificate '%Y'", cert->get_subject(cert));
+
+	this->creds->add_cert(this->creds, TRUE, cert);
+
+	return create_reply(NULL);
+}
+
+CALLBACK(load_key, vici_message_t*,
+	private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+	key_type_t type;
+	private_key_t *key;
+	chunk_t data;
+	char *str;
+
+	str = message->get_str(message, NULL, "type");
+	if (!str)
+	{
+		return create_reply("key type missing");
+	}
+	if (strcaseeq(str, "any"))
+	{
+		type = KEY_ANY;
+	}
+	else if (strcaseeq(str, "rsa"))
+	{
+		type = KEY_RSA;
+	}
+	else if (strcaseeq(str, "ecdsa"))
+	{
+		type = KEY_ECDSA;
+	}
+	else
+	{
+		return create_reply("invalid key type: %s", str);
+	}
+	data = message->get_value(message, chunk_empty, "data");
+	if (!data.len)
+	{
+		return create_reply("key data missing");
+	}
+	key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
+							 BUILD_BLOB_PEM, data, BUILD_END);
+	if (!key)
+	{
+		return create_reply("parsing %N private key failed",
+							key_type_names, type);
+	}
+
+	DBG1(DBG_CFG, "loaded %N private key", key_type_names, type);
+
+	this->creds->add_key(this->creds, key);
+
+	return create_reply(NULL);
+}
+
+CALLBACK(shared_owners, bool,
+	linked_list_t *owners, vici_message_t *message, char *name, chunk_t value)
+{
+	if (streq(name, "owners"))
+	{
+		char buf[256];
+
+		if (!vici_stringify(value, buf, sizeof(buf)))
+		{
+			return FALSE;
+		}
+		owners->insert_last(owners, identification_create_from_string(buf));
+	}
+	return TRUE;
+}
+
+CALLBACK(load_shared, vici_message_t*,
+	private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+	shared_key_type_t type;
+	linked_list_t *owners;
+	chunk_t data;
+	char *str, buf[512] = "";
+	enumerator_t *enumerator;
+	identification_t *owner;
+	int len;
+
+	str = message->get_str(message, NULL, "type");
+	if (!str)
+	{
+		return create_reply("shared key type missing");
+	}
+	if (strcaseeq(str, "ike"))
+	{
+		type = SHARED_IKE;
+	}
+	else if (strcaseeq(str, "eap") || streq(str, "xauth"))
+	{
+		type = SHARED_EAP;
+	}
+	else
+	{
+		return create_reply("invalid shared key type: %s", str);
+	}
+	data = message->get_value(message, chunk_empty, "data");
+	if (!data.len)
+	{
+		return create_reply("shared key data missing");
+	}
+
+	owners = linked_list_create();
+	if (!message->parse(message, NULL, NULL, NULL, shared_owners, owners))
+	{
+		owners->destroy_offset(owners, offsetof(identification_t, destroy));
+		return create_reply("parsing shared key owners failed");
+	}
+	if (owners->get_count(owners) == 0)
+	{
+		owners->insert_last(owners, identification_create_from_string("%any"));
+	}
+
+	enumerator = owners->create_enumerator(owners);
+	while (enumerator->enumerate(enumerator, &owner))
+	{
+		len = strlen(buf);
+		if (len < sizeof(buf))
+		{
+			snprintf(buf + len, sizeof(buf) - len, "%s'%Y'",
+					 len ? ", " : "", owner);
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	DBG1(DBG_CFG, "loaded %N shared key for: %s",
+		 shared_key_type_names, type, buf);
+
+	this->creds->add_shared_list(this->creds,
+						shared_key_create(type, chunk_clone(data)), owners);
+
+	return create_reply(NULL);
+}
+
+CALLBACK(clear_creds, vici_message_t*,
+	private_vici_cred_t *this, char *name, u_int id, vici_message_t *message)
+{
+	vici_builder_t *builder;
+
+	this->creds->clear(this->creds);
+	lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
+
+	builder = vici_builder_create();
+	return builder->finalize(builder);
+}
+
+static void manage_command(private_vici_cred_t *this,
+						   char *name, vici_command_cb_t cb, bool reg)
+{
+	this->dispatcher->manage_command(this->dispatcher, name,
+									 reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_cred_t *this, bool reg)
+{
+	manage_command(this, "clear-creds", clear_creds, reg);
+	manage_command(this, "load-cert", load_cert, reg);
+	manage_command(this, "load-key", load_key, reg);
+	manage_command(this, "load-shared", load_shared, reg);
+}
+
+METHOD(vici_cred_t, destroy, void,
+	private_vici_cred_t *this)
+{
+	manage_commands(this, FALSE);
+
+	lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+	this->creds->destroy(this->creds);
+	free(this);
+}
+
+/**
+ * See header
+ */
+vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher)
+{
+	private_vici_cred_t *this;
+
+	INIT(this,
+		.public = {
+			.destroy = _destroy,
+		},
+		.dispatcher = dispatcher,
+		.creds = mem_cred_create(),
+	);
+
+	lib->credmgr->add_set(lib->credmgr, &this->creds->set);
+
+	manage_commands(this, TRUE);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_cred.h b/src/libcharon/plugins/vici/vici_cred.h
new file mode 100644
index 0000000..e109a27
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cred.h
@@ -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.
+ */
+
+/**
+ * @defgroup vici_cred vici_cred
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_CRED_H_
+#define VICI_CRED_H_
+
+#include "vici_dispatcher.h"
+
+typedef struct vici_cred_t vici_cred_t;
+
+/**
+ * In-memory credential backend, managed by VICI.
+ */
+struct vici_cred_t {
+
+	/**
+	 * Destroy a vici_cred_t.
+	 */
+	void (*destroy)(vici_cred_t *this);
+};
+
+/**
+ * Create a vici_cred instance.
+ *
+ * @param dispatcher		dispatcher to receive requests from
+ * @return					credential backend
+ */
+vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_CRED_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.c b/src/libcharon/plugins/vici/vici_dispatcher.c
new file mode 100644
index 0000000..6db36fb
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_dispatcher.c
@@ -0,0 +1,524 @@
+/*
+ * 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 "vici_dispatcher.h"
+#include "vici_socket.h"
+
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <threading/thread.h>
+#include <collections/array.h>
+#include <collections/hashtable.h>
+
+typedef struct private_vici_dispatcher_t private_vici_dispatcher_t;
+
+/**
+ * Private data of an vici_dispatcher_t object.
+ */
+struct private_vici_dispatcher_t {
+
+	/**
+	 * Public vici_dispatcher_t interface.
+	 */
+	vici_dispatcher_t public;
+
+	/**
+	 * Socket to send/receive messages
+	 */
+	vici_socket_t *socket;
+
+	/**
+	 * List of registered commands (char* => command_t*)
+	 */
+	hashtable_t *cmds;
+
+	/**
+	 * List of known events, and registered clients (char* => event_t*)
+	 */
+	hashtable_t *events;
+
+	/**
+	 * Mutex to lock hashtables
+	 */
+	mutex_t *mutex;
+
+	/**
+	 * Condvar to signal command termination
+	 */
+	condvar_t *cond;
+};
+
+/**
+ * Registered command
+ */
+typedef struct {
+	/** command name */
+	char *name;
+	/** callback for command */
+	vici_command_cb_t cb;
+	/** user data to pass to callback */
+	void *user;
+	/** command currently in use? */
+	u_int uses;
+} command_t;
+
+/**
+ * Registered event
+ */
+typedef struct {
+	/** event name */
+	char *name;
+	/** registered clients, as u_int */
+	array_t *clients;
+	/** event currently in use? */
+	u_int uses;
+} event_t;
+
+/**
+ * Send a operation code, optionally with name and message
+ */
+static void send_op(private_vici_dispatcher_t *this, u_int id,
+					vici_operation_t op, char *name, vici_message_t *message)
+{
+	bio_writer_t *writer;
+	u_int len;
+
+	len = sizeof(u_int8_t);
+	if (name)
+	{
+		len += sizeof(u_int8_t) + strlen(name);
+	}
+	if (message)
+	{
+		len += message->get_encoding(message).len;
+	}
+	writer = bio_writer_create(len);
+	writer->write_uint8(writer, op);
+	if (name)
+	{
+		writer->write_data8(writer, chunk_from_str(name));
+	}
+	if (message)
+	{
+		writer->write_data(writer, message->get_encoding(message));
+	}
+	this->socket->send(this->socket, id, writer->extract_buf(writer));
+	writer->destroy(writer);
+}
+
+/**
+ * Register client for event
+ */
+static void register_event(private_vici_dispatcher_t *this, char *name,
+						   u_int id)
+{
+	event_t *event;
+
+	this->mutex->lock(this->mutex);
+	while (TRUE)
+	{
+		event = this->events->get(this->events, name);
+		if (!event)
+		{
+			break;
+		}
+		if (!event->uses)
+		{
+			array_insert(event->clients, ARRAY_TAIL, &id);
+			break;
+		}
+		this->cond->wait(this->cond, this->mutex);
+	}
+	this->mutex->unlock(this->mutex);
+
+	if (event)
+	{
+		DBG2(DBG_CFG, "vici client %u registered for: %s", id, name);
+		send_op(this, id, VICI_EVENT_CONFIRM, NULL, NULL);
+	}
+	else
+	{
+		DBG1(DBG_CFG, "vici client %u invalid registration: %s", id, name);
+		send_op(this, id, VICI_EVENT_UNKNOWN, NULL, NULL);
+	}
+}
+
+/**
+ * Unregister client for event
+ */
+static void unregister_event(private_vici_dispatcher_t *this, char *name,
+							 u_int id)
+{
+	enumerator_t *enumerator;
+	event_t *event;
+	u_int *current;
+	bool found = FALSE;
+
+	this->mutex->lock(this->mutex);
+	while (TRUE)
+	{
+		event = this->events->get(this->events, name);
+		if (!event)
+		{
+			break;
+		}
+		if (!event->uses)
+		{
+			enumerator = array_create_enumerator(event->clients);
+			while (enumerator->enumerate(enumerator, &current))
+			{
+				if (*current == id)
+				{
+					array_remove_at(event->clients, enumerator);
+					found = TRUE;
+					break;
+				}
+			}
+			enumerator->destroy(enumerator);
+			break;
+		}
+		this->cond->wait(this->cond, this->mutex);
+	}
+	this->mutex->unlock(this->mutex);
+
+	DBG2(DBG_CFG, "vici client %u unregistered for: %s", id, name);
+
+	if (found)
+	{
+		send_op(this, id, VICI_EVENT_CONFIRM, NULL, NULL);
+	}
+	else
+	{
+		send_op(this, id, VICI_EVENT_UNKNOWN, NULL, NULL);
+	}
+}
+
+/**
+ * Data to release on thread cancellation
+ */
+typedef struct {
+	private_vici_dispatcher_t *this;
+	command_t *cmd;
+	vici_message_t *request;
+} release_data_t;
+
+/**
+ * Release command after execution/cancellation
+ */
+CALLBACK(release_command, void,
+	release_data_t *release)
+{
+	release->request->destroy(release->request);
+
+	release->this->mutex->lock(release->this->mutex);
+	if (--release->cmd->uses == 0)
+	{
+		release->this->cond->broadcast(release->this->cond);
+	}
+	release->this->mutex->unlock(release->this->mutex);
+
+	free(release);
+}
+
+/**
+ * Process a request message
+ */
+void process_request(private_vici_dispatcher_t *this, char *name, u_int id,
+					 chunk_t data)
+{
+	vici_message_t *response = NULL;
+	release_data_t *release;
+	command_t *cmd;
+
+	this->mutex->lock(this->mutex);
+	cmd = this->cmds->get(this->cmds, name);
+	if (cmd)
+	{
+		cmd->uses++;
+	}
+	this->mutex->unlock(this->mutex);
+
+	if (cmd)
+	{
+		INIT(release,
+			.this = this,
+			.cmd = cmd,
+		);
+
+		DBG2(DBG_CFG, "vici client %u requests: %s", id, name);
+
+		thread_cleanup_push(release_command, release);
+
+		release->request = vici_message_create_from_data(data, FALSE);
+		response = release->cmd->cb(cmd->user, cmd->name, id, release->request);
+
+		thread_cleanup_pop(TRUE);
+
+		if (response)
+		{
+			send_op(this, id, VICI_CMD_RESPONSE, NULL, response);
+			response->destroy(response);
+		}
+	}
+	else
+	{
+		DBG1(DBG_CFG, "vici client %u invalid request: %s", id, name);
+		send_op(this, id, VICI_CMD_UNKNOWN, NULL, NULL);
+	}
+}
+
+CALLBACK(inbound, void,
+	private_vici_dispatcher_t *this, u_int id, chunk_t data)
+{
+	bio_reader_t *reader;
+	chunk_t chunk;
+	u_int8_t type;
+	char name[257];
+
+	reader = bio_reader_create(data);
+	if (reader->read_uint8(reader, &type))
+	{
+		switch (type)
+		{
+			case VICI_EVENT_REGISTER:
+				if (reader->read_data8(reader, &chunk) &&
+					vici_stringify(chunk, name, sizeof(name)))
+				{
+					register_event(this, name, id);
+				}
+				else
+				{
+					DBG1(DBG_CFG, "invalid vici register message");
+				}
+				break;
+			case VICI_EVENT_UNREGISTER:
+				if (reader->read_data8(reader, &chunk) &&
+					vici_stringify(chunk, name, sizeof(name)))
+				{
+					unregister_event(this, name, id);
+				}
+				else
+				{
+					DBG1(DBG_CFG, "invalid vici unregister message");
+				}
+				break;
+			case VICI_CMD_REQUEST:
+				if (reader->read_data8(reader, &chunk) &&
+					vici_stringify(chunk, name, sizeof(name)))
+				{
+					thread_cleanup_push((void*)reader->destroy, reader);
+					process_request(this, name, id, reader->peek(reader));
+					thread_cleanup_pop(FALSE);
+				}
+				else
+				{
+					DBG1(DBG_CFG, "invalid vici request message");
+				}
+				break;
+			case VICI_CMD_RESPONSE:
+			case VICI_EVENT_CONFIRM:
+			case VICI_EVENT_UNKNOWN:
+			case VICI_EVENT:
+			default:
+				DBG1(DBG_CFG, "unsupported vici operation: %u", type);
+				break;
+		}
+	}
+	else
+	{
+		DBG1(DBG_CFG, "invalid vici message");
+	}
+	reader->destroy(reader);
+}
+
+CALLBACK(connect_, void,
+	private_vici_dispatcher_t *this, u_int id)
+{
+	DBG2(DBG_CFG, "vici client %u connected", id);
+}
+
+CALLBACK(disconnect, void,
+	private_vici_dispatcher_t *this, u_int id)
+{
+	enumerator_t *events, *ids;
+	event_t *event;
+	u_int *current;
+
+	/* deregister client from all events */
+	this->mutex->lock(this->mutex);
+	events = this->events->create_enumerator(this->events);
+	while (events->enumerate(events, NULL, &event))
+	{
+		while (event->uses)
+		{
+			this->cond->wait(this->cond, this->mutex);
+		}
+		ids = array_create_enumerator(event->clients);
+		while (ids->enumerate(ids, &current))
+		{
+			if (id == *current)
+			{
+				array_remove_at(event->clients, ids);
+			}
+		}
+		ids->destroy(ids);
+	}
+	events->destroy(events);
+	this->mutex->unlock(this->mutex);
+
+	DBG2(DBG_CFG, "vici client %u disconnected", id);
+}
+
+METHOD(vici_dispatcher_t, manage_command, void,
+	private_vici_dispatcher_t *this, char *name,
+	vici_command_cb_t cb, void *user)
+{
+	command_t *cmd;
+
+	this->mutex->lock(this->mutex);
+	if (cb)
+	{
+		INIT(cmd,
+			.name = strdup(name),
+			.cb = cb,
+			.user = user,
+		);
+		cmd = this->cmds->put(this->cmds, cmd->name, cmd);
+	}
+	else
+	{
+		cmd = this->cmds->remove(this->cmds, name);
+	}
+	if (cmd)
+	{
+		while (cmd->uses)
+		{
+			this->cond->wait(this->cond, this->mutex);
+		}
+		free(cmd->name);
+		free(cmd);
+	}
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(vici_dispatcher_t, manage_event, void,
+	private_vici_dispatcher_t *this, char *name, bool reg)
+{
+	event_t *event;
+
+	this->mutex->lock(this->mutex);
+	if (reg)
+	{
+		INIT(event,
+			.name = strdup(name),
+			.clients = array_create(sizeof(u_int), 0),
+		);
+		event = this->events->put(this->events, event->name, event);
+	}
+	else
+	{
+		event = this->events->remove(this->events, name);
+	}
+	if (event)
+	{
+		while (event->uses)
+		{
+			this->cond->wait(this->cond, this->mutex);
+		}
+		array_destroy(event->clients);
+		free(event->name);
+		free(event);
+	}
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(vici_dispatcher_t, raise_event, void,
+	private_vici_dispatcher_t *this, char *name, u_int id,
+	vici_message_t *message)
+{
+	enumerator_t *enumerator;
+	event_t *event;
+	u_int *current;
+
+	this->mutex->lock(this->mutex);
+	event = this->events->get(this->events, name);
+	if (event)
+	{
+		event->uses++;
+		this->mutex->unlock(this->mutex);
+
+		enumerator = array_create_enumerator(event->clients);
+		while (enumerator->enumerate(enumerator, &current))
+		{
+			if (id == 0 || id == *current)
+			{
+				send_op(this, *current, VICI_EVENT, name, message);
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		this->mutex->lock(this->mutex);
+		if (--event->uses == 0)
+		{
+			this->cond->broadcast(this->cond);
+		}
+	}
+	this->mutex->unlock(this->mutex);
+
+	message->destroy(message);
+}
+
+METHOD(vici_dispatcher_t, destroy, void,
+	private_vici_dispatcher_t *this)
+{
+	DESTROY_IF(this->socket);
+	this->mutex->destroy(this->mutex);
+	this->cond->destroy(this->cond);
+	this->cmds->destroy(this->cmds);
+	this->events->destroy(this->events);
+	free(this);
+}
+
+/**
+ * See header
+ */
+vici_dispatcher_t *vici_dispatcher_create(char *uri)
+{
+	private_vici_dispatcher_t *this;
+
+	INIT(this,
+		.public = {
+			.manage_command = _manage_command,
+			.manage_event = _manage_event,
+			.raise_event = _raise_event,
+			.destroy = _destroy,
+		},
+		.cmds = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
+		.events = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1),
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.cond = condvar_create(CONDVAR_TYPE_DEFAULT),
+	);
+
+	this->socket = vici_socket_create(uri, inbound, connect_, disconnect, this);
+	if (!this->socket)
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.h b/src/libcharon/plugins/vici/vici_dispatcher.h
new file mode 100644
index 0000000..2297a80
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_dispatcher.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup vici_dispatcher vici_dispatcher
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_DISPATCHER_H_
+#define VICI_DISPATCHER_H_
+
+#include "vici_message.h"
+
+typedef struct vici_dispatcher_t vici_dispatcher_t;
+typedef enum vici_operation_t vici_operation_t;
+
+/**
+ * Default socket URI of vici service
+ */
+#ifdef WIN32
+# define VICI_DEFAULT_URI "tcp://127.0.0.1:4502"
+#else
+# define VICI_DEFAULT_URI "unix://" IPSEC_PIDDIR "/charon.vici"
+#endif
+
+/**
+ * Kind of vici operation
+ */
+enum vici_operation_t {
+	/** a named request message */
+	VICI_CMD_REQUEST,
+	/** an unnamed response message to a request */
+	VICI_CMD_RESPONSE,
+	/** unnamed response if requested command is unknown */
+	VICI_CMD_UNKNOWN,
+	/** a named event registration request */
+	VICI_EVENT_REGISTER,
+	/** a named event unregistration request */
+	VICI_EVENT_UNREGISTER,
+	/** unnamed response for successful event (un-)registration */
+	VICI_EVENT_CONFIRM,
+	/** unnamed response if event (un-)registration failed */
+	VICI_EVENT_UNKNOWN,
+	/** a named event message */
+	VICI_EVENT,
+};
+
+/**
+ * Vici command callback function
+ *
+ * @param user			user data, as supplied during registration
+ * @param name			name of the command it has been registered under
+ * @param id			client connection identifier
+ * @param request		request message data
+ * @return				response message
+ */
+typedef vici_message_t* (*vici_command_cb_t)(void *user, char *name, u_int id,
+											 vici_message_t *request);
+
+/**
+ * Vici command dispatcher.
+ */
+struct vici_dispatcher_t {
+
+	/**
+	 * Register/Unregister a callback invoked for a specific command request.
+	 *
+	 * @param name			name of the command
+	 * @param cb			callback function to register, NULL to unregister
+	 * @param user			user data to pass to callback
+	 */
+	void (*manage_command)(vici_dispatcher_t *this, char *name,
+						   vici_command_cb_t cb, void *user);
+
+	/**
+	 * Register/Unregister an event type to send.
+	 *
+	 * The dispatcher internally manages event subscriptions. Clients registered
+	 * for an event will receive such messages when the event is raised.
+	 *
+	 * @param name			event name to manager
+	 * @param reg			TRUE to register, FALSE to unregister
+	 */
+	void (*manage_event)(vici_dispatcher_t *this, char *name, bool reg);
+
+	/**
+	 * Raise an event to a specific or all clients registered to that event.
+	 *
+	 * @param name			event name to raise
+	 * @param id			client connection ID, 0 for all
+	 * @param message		event message to send, gets destroyed
+	 */
+	void (*raise_event)(vici_dispatcher_t *this, char *name, u_int id,
+						vici_message_t *message);
+
+	/**
+	 * Destroy a vici_dispatcher_t.
+	 */
+	void (*destroy)(vici_dispatcher_t *this);
+};
+
+/**
+ * Create a vici_dispatcher instance.
+ *
+ * @param uri		uri for listening stream service
+ * @return			dispatcher instance
+ */
+vici_dispatcher_t *vici_dispatcher_create(char *uri);
+
+#endif /** VICI_DISPATCHER_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_logger.c b/src/libcharon/plugins/vici/vici_logger.c
new file mode 100644
index 0000000..cffd65b
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_logger.c
@@ -0,0 +1,130 @@
+/*
+ * 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 "vici_logger.h"
+#include "vici_builder.h"
+
+#include <daemon.h>
+#include <threading/mutex.h>
+
+typedef struct private_vici_logger_t private_vici_logger_t;
+
+/**
+ * Private data of an vici_logger_t object.
+ */
+struct private_vici_logger_t {
+
+	/**
+	 * Public vici_logger_t interface.
+	 */
+	vici_logger_t public;
+
+	/**
+	 * Dispatcher
+	 */
+	vici_dispatcher_t *dispatcher;
+
+	/**
+	 * Recursiveness avoidance counter
+	 */
+	int recursive;
+
+	/**
+	 * Mutex to synchronize logging
+	 */
+	mutex_t *mutex;
+};
+
+METHOD(logger_t, log_, void,
+	private_vici_logger_t *this, debug_t group, level_t level, int thread,
+	ike_sa_t* ike_sa, const char *msg)
+{
+	this->mutex->lock(this->mutex);
+
+	/* avoid recursive invocations by the vici subsystem */
+	if (this->recursive++ == 0)
+	{
+		vici_message_t *message;
+		vici_builder_t *builder;
+
+		builder = vici_builder_create();
+		builder->add_kv(builder, "group", "%N", debug_names, group);
+		builder->add_kv(builder, "level", "%d", level);
+		builder->add_kv(builder, "thread", "%d", thread);
+		if (ike_sa)
+		{
+			builder->add_kv(builder, "ikesa-name", "%s",
+							ike_sa->get_name(ike_sa));
+			builder->add_kv(builder, "ikesa-uniqueid", "%u",
+							ike_sa->get_unique_id(ike_sa));
+		}
+		builder->add_kv(builder, "msg", "%s", msg);
+
+		message = builder->finalize(builder);
+		if (message)
+		{
+			this->dispatcher->raise_event(this->dispatcher, "log", 0, message);
+		}
+	}
+	this->recursive--;
+
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(logger_t, get_level, level_t,
+	private_vici_logger_t *this, debug_t group)
+{
+	return LEVEL_CTRL;
+}
+
+/**
+ * (Un-)register dispatcher functions/events
+ */
+static void manage_commands(private_vici_logger_t *this, bool reg)
+{
+	this->dispatcher->manage_event(this->dispatcher, "log", reg);
+}
+
+METHOD(vici_logger_t, destroy, void,
+	private_vici_logger_t *this)
+{
+	manage_commands(this, FALSE);
+	this->mutex->destroy(this->mutex);
+	free(this);
+}
+
+/**
+ * See header
+ */
+vici_logger_t *vici_logger_create(vici_dispatcher_t *dispatcher)
+{
+	private_vici_logger_t *this;
+
+	INIT(this,
+		.public = {
+			.logger = {
+				.log = _log_,
+				.get_level = _get_level,
+			},
+			.destroy = _destroy,
+		},
+		.dispatcher = dispatcher,
+		.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
+	);
+
+	manage_commands(this, TRUE);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_logger.h b/src/libcharon/plugins/vici/vici_logger.h
new file mode 100644
index 0000000..7be1d60
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_logger.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup vici_logger vici_logger
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_LOGGER_H_
+#define VICI_LOGGER_H_
+
+#include "vici_dispatcher.h"
+
+#include <bus/listeners/logger.h>
+
+typedef struct vici_logger_t vici_logger_t;
+
+/**
+ * Generic debugging logger over vici.
+ */
+struct vici_logger_t {
+
+	/**
+	 * Implements logger interface.
+	 */
+	logger_t logger;
+
+	/**
+	 * Destroy a vici_logger_t.
+	 */
+	void (*destroy)(vici_logger_t *this);
+};
+
+/**
+ * Create a vici_logger instance.
+ *
+ * @param dispatcher		dispatcher to receive requests from
+ * @return					loggerential backend
+ */
+vici_logger_t *vici_logger_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_LOGGER_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_message.c b/src/libcharon/plugins/vici/vici_message.c
new file mode 100644
index 0000000..dcc175f
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_message.c
@@ -0,0 +1,727 @@
+/*
+ * 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 "vici_message.h"
+#include "vici_builder.h"
+
+#include <bio/bio_reader.h>
+#include <bio/bio_writer.h>
+
+#include <errno.h>
+
+typedef struct private_vici_message_t private_vici_message_t;
+
+/**
+ * Private data of an vici_message_t object.
+ */
+struct private_vici_message_t {
+
+	/**
+	 * Public vici_message_t interface.
+	 */
+	vici_message_t public;
+
+	/**
+	 * Message encoding
+	 */
+	chunk_t encoding;
+
+	/**
+	 * Free encoding during destruction?
+	 */
+	bool cleanup;
+
+	/**
+	 * Allocated strings we maintain for get_str()
+	 */
+	linked_list_t *strings;
+};
+
+ENUM(vici_type_names, VICI_START, VICI_END,
+	"start",
+	"section-start",
+	"section-end",
+	"key-value",
+	"list-start",
+	"list-item",
+	"list-end",
+	"end"
+);
+
+/**
+ * See header.
+ */
+bool vici_stringify(chunk_t chunk, char *buf, size_t size)
+{
+	if (!chunk_printable(chunk, NULL, 0))
+	{
+		return FALSE;
+	}
+	snprintf(buf, size, "%.*s", (int)chunk.len, chunk.ptr);
+	return TRUE;
+}
+
+/**
+ * See header.
+ */
+bool vici_verify_type(vici_type_t type, u_int section, bool list)
+{
+	if (list)
+	{
+		if (type != VICI_LIST_END && type != VICI_LIST_ITEM)
+		{
+			DBG1(DBG_ENC, "'%N' within list", vici_type_names, type);
+			return FALSE;
+		}
+	}
+	else
+	{
+		if (type == VICI_LIST_ITEM || type == VICI_LIST_END)
+		{
+			DBG1(DBG_ENC, "'%N' outside list", vici_type_names, type);
+			return FALSE;
+		}
+	}
+	if (type == VICI_SECTION_END && section == 0)
+	{
+		DBG1(DBG_ENC, "'%N' outside of section", vici_type_names, type);
+		return FALSE;
+	}
+	if (type == VICI_END)
+	{
+		if (section)
+		{
+			DBG1(DBG_ENC, "'%N' within section", vici_type_names, type);
+			return FALSE;
+		}
+		if (list)
+		{
+			DBG1(DBG_ENC, "'%N' within list", vici_type_names, type);
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * Enumerator parsing message
+ */
+typedef struct {
+	/* implements enumerator */
+	enumerator_t public;
+	/** reader to parse from */
+	bio_reader_t *reader;
+	/** section nesting level */
+	int section;
+	/** currently parsing list? */
+	bool list;
+	/** string currently enumerating */
+	char name[257];
+} parse_enumerator_t;
+
+METHOD(enumerator_t, parse_enumerate, bool,
+	parse_enumerator_t *this, vici_type_t *out, char **name, chunk_t *value)
+{
+	u_int8_t type;
+	chunk_t data;
+
+	if (!this->reader->remaining(this->reader) ||
+		!this->reader->read_uint8(this->reader, &type))
+	{
+		*out = VICI_END;
+		return TRUE;
+	}
+	if (!vici_verify_type(type, this->section, this->list))
+	{
+		return FALSE;
+	}
+
+	switch (type)
+	{
+		case VICI_SECTION_START:
+			if (!this->reader->read_data8(this->reader, &data) ||
+				!vici_stringify(data, this->name, sizeof(this->name)))
+			{
+				DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
+				return FALSE;
+			}
+			*name = this->name;
+			this->section++;
+			break;
+		case VICI_SECTION_END:
+			this->section--;
+			break;
+		case VICI_KEY_VALUE:
+			if (!this->reader->read_data8(this->reader, &data) ||
+				!vici_stringify(data, this->name, sizeof(this->name)) ||
+				!this->reader->read_data16(this->reader, value))
+			{
+				DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
+				return FALSE;
+			}
+			*name = this->name;
+			break;
+		case VICI_LIST_START:
+			if (!this->reader->read_data8(this->reader, &data) ||
+				!vici_stringify(data, this->name, sizeof(this->name)))
+			{
+				DBG1(DBG_ENC, "invalid '%N' encoding", vici_type_names, type);
+				return FALSE;
+			}
+			*name = this->name;
+			this->list = TRUE;
+			break;
+		case VICI_LIST_ITEM:
+			this->reader->read_data16(this->reader, value);
+			break;
+		case VICI_LIST_END:
+			this->list = FALSE;
+			break;
+		case VICI_END:
+			return TRUE;
+		default:
+			DBG1(DBG_ENC, "unknown encoding type: %u", type);
+			return FALSE;
+	}
+
+	*out = type;
+
+	return TRUE;
+}
+
+METHOD(enumerator_t, parse_destroy, void,
+	parse_enumerator_t *this)
+{
+	this->reader->destroy(this->reader);
+	free(this);
+}
+
+METHOD(vici_message_t, create_enumerator, enumerator_t*,
+	private_vici_message_t *this)
+{
+	parse_enumerator_t *enumerator;
+
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)_parse_enumerate,
+			.destroy = _parse_destroy,
+		},
+		.reader = bio_reader_create(this->encoding),
+	);
+
+	return &enumerator->public;
+}
+
+/**
+ * Find a value for given vararg key
+ */
+static bool find_value(private_vici_message_t *this, chunk_t *value,
+					   char *fmt, va_list args)
+{
+	enumerator_t *enumerator;
+	char buf[128], *name, *key, *dot, *next;
+	int section = 0, keysection = 0;
+	bool found = FALSE;
+	chunk_t current;
+	vici_type_t type;
+
+	vsnprintf(buf, sizeof(buf), fmt, args);
+	next = buf;
+
+	enumerator = create_enumerator(this);
+
+	/* descent into section */
+	while (TRUE)
+	{
+		dot = strchr(next, '.');
+		if (!dot)
+		{
+			key = next;
+			break;
+		}
+		*dot = '\0';
+		key = next;
+		next = dot + 1;
+		keysection++;
+
+		while (enumerator->enumerate(enumerator, &type, &name, &current))
+		{
+			switch (type)
+			{
+				case VICI_SECTION_START:
+					section++;
+					if (section == keysection && streq(name, key))
+					{
+						break;
+					}
+					continue;
+				case VICI_SECTION_END:
+					section--;
+					continue;
+				case VICI_END:
+					break;
+				default:
+					continue;
+			}
+			break;
+		}
+	}
+
+	/* find key/value in current section */
+	while (enumerator->enumerate(enumerator, &type, &name, &current))
+	{
+		switch (type)
+		{
+			case VICI_KEY_VALUE:
+				if (section == keysection && streq(key, name))
+				{
+					*value = current;
+					found = TRUE;
+					break;
+				}
+				continue;
+			case VICI_SECTION_START:
+				section++;
+				continue;
+			case VICI_SECTION_END:
+				section--;
+				continue;
+			case VICI_END:
+				break;
+			default:
+				continue;
+		}
+		break;
+	}
+
+	enumerator->destroy(enumerator);
+
+	return found;
+}
+
+METHOD(vici_message_t, vget_str, char*,
+	private_vici_message_t *this, char *def, char *fmt, va_list args)
+{
+	chunk_t value;
+	bool found;
+	char *str;
+
+	found = find_value(this, &value, fmt, args);
+	if (found)
+	{
+		if (chunk_printable(value, NULL, 0))
+		{
+			str = strndup(value.ptr, value.len);
+			/* keep a reference to string, so caller doesn't have to care */
+			this->strings->insert_last(this->strings, str);
+			return str;
+		}
+	}
+	return def;
+}
+
+METHOD(vici_message_t, get_str, char*,
+	private_vici_message_t *this, char *def, char *fmt, ...)
+{
+	va_list args;
+	char *str;
+
+	va_start(args, fmt);
+	str = vget_str(this, def, fmt, args);
+	va_end(args);
+	return str;
+}
+
+METHOD(vici_message_t, vget_int, int,
+	private_vici_message_t *this, int def, char *fmt, va_list args)
+{
+	chunk_t value;
+	bool found;
+	char buf[32], *pos;
+	int ret;
+
+	found = find_value(this, &value, fmt, args);
+	if (found)
+	{
+		if (chunk_printable(value, NULL, 0))
+		{
+			snprintf(buf, sizeof(buf), "%.*s", (int)value.len, value.ptr);
+			errno = 0;
+			ret = strtol(buf, &pos, 0);
+			if (errno == 0 && pos == buf + strlen(buf))
+			{
+				return ret;
+			}
+		}
+	}
+	return def;
+}
+
+METHOD(vici_message_t, get_int, int,
+	private_vici_message_t *this, int def, char *fmt, ...)
+{
+	va_list args;
+	int val;
+
+	va_start(args, fmt);
+	val = vget_int(this, def, fmt, args);
+	va_end(args);
+	return val;
+}
+
+METHOD(vici_message_t, vget_value, chunk_t,
+	private_vici_message_t *this, chunk_t def, char *fmt, va_list args)
+{
+	chunk_t value;
+	bool found;
+
+	found = find_value(this, &value, fmt, args);
+	if (found)
+	{
+		return value;
+	}
+	return def;
+}
+
+METHOD(vici_message_t, get_value, chunk_t,
+	private_vici_message_t *this, chunk_t def, char *fmt, ...)
+{
+	va_list args;
+	chunk_t value;
+
+	va_start(args, fmt);
+	value = vget_value(this, def, fmt, args);
+	va_end(args);
+	return value;
+}
+
+METHOD(vici_message_t, get_encoding, chunk_t,
+	private_vici_message_t *this)
+{
+	return this->encoding;
+}
+
+/**
+ * Private parse context data
+ */
+struct vici_parse_context_t {
+	/** current section nesting level */
+	int level;
+	/** parse enumerator */
+	enumerator_t *e;
+};
+
+METHOD(vici_message_t, parse, bool,
+	private_vici_message_t *this, vici_parse_context_t *ctx,
+	vici_section_cb_t section, vici_value_cb_t kv, vici_value_cb_t li,
+	void *user)
+{
+	vici_parse_context_t root = {};
+	char *name, *list = NULL;
+	vici_type_t type;
+	chunk_t value;
+	int base;
+	bool ok = TRUE;
+
+	if (!ctx)
+	{
+		ctx = &root;
+		root.e = create_enumerator(this);
+	}
+
+	base = ctx->level;
+
+	while (ok)
+	{
+		ok = ctx->e->enumerate(ctx->e, &type, &name, &value);
+		if (ok)
+		{
+			switch (type)
+			{
+				case VICI_START:
+					/* should never occur */
+					continue;
+				case VICI_KEY_VALUE:
+					if (ctx->level == base && kv)
+					{
+						name = strdup(name);
+						this->strings->insert_last(this->strings, name);
+						ok = kv(user, &this->public, name, value);
+					}
+					continue;
+				case VICI_LIST_START:
+					if (ctx->level == base)
+					{
+						list = strdup(name);
+						this->strings->insert_last(this->strings, list);
+					}
+					continue;
+				case VICI_LIST_ITEM:
+					if (list && li)
+					{
+						name = strdup(name);
+						this->strings->insert_last(this->strings, name);
+						ok = li(user, &this->public, list, value);
+					}
+					continue;
+				case VICI_LIST_END:
+					if (ctx->level == base)
+					{
+						list = NULL;
+					}
+					continue;
+				case VICI_SECTION_START:
+					if (ctx->level++ == base && section)
+					{
+						name = strdup(name);
+						this->strings->insert_last(this->strings, name);
+						ok = section(user, &this->public, ctx, name);
+					}
+					continue;
+				case VICI_SECTION_END:
+					if (ctx->level-- == base)
+					{
+						break;
+					}
+					continue;
+				case VICI_END:
+					break;
+			}
+		}
+		break;
+	}
+
+	if (ctx == &root)
+	{
+		root.e->destroy(root.e);
+	}
+	return ok;
+}
+
+METHOD(vici_message_t, dump, bool,
+	private_vici_message_t *this, char *label, bool pretty, FILE *out)
+{
+	enumerator_t *enumerator;
+	int ident = 0, delta;
+	vici_type_t type, last_type = VICI_START;
+	char *name, *term, *sep, *separ, *assign;
+	chunk_t value;
+
+	/* pretty print uses indentation on multiple lines */
+	if (pretty)
+	{
+		delta  = 2;
+		term   = "\n";
+		separ  = "";
+		assign = " = ";
+	}
+	else
+	{
+		delta  = 0;
+		term   = "";
+		separ  = " ";
+		assign = "=";
+	}
+
+	fprintf(out, "%s {%s", label, term);
+	ident += delta;
+
+	enumerator = create_enumerator(this);
+	while (enumerator->enumerate(enumerator, &type, &name, &value))
+	{
+		switch (type)
+		{
+			case VICI_START:
+				/* should never occur */
+				break;
+			case VICI_SECTION_START:
+				sep = (last_type != VICI_SECTION_START &&
+					   last_type != VICI_START) ? separ : "";
+				fprintf(out, "%*s%s%s {%s", ident, "", sep, name, term);
+				ident += delta;
+				break;
+			case VICI_SECTION_END:
+				ident -= delta;
+				fprintf(out, "%*s}%s", ident, "", term);
+				break;
+			case VICI_KEY_VALUE:
+				sep = (last_type != VICI_SECTION_START &&
+					   last_type != VICI_START) ? separ : "";
+				if (chunk_printable(value, NULL, ' '))
+				{
+					fprintf(out, "%*s%s%s%s%.*s%s", ident, "", sep, name,
+							assign, (int)value.len, value.ptr, term);
+				}
+				else
+				{
+					fprintf(out, "%*s%s%s%s0x%+#B%s", ident, "", sep, name,
+							assign, &value, term);
+				}
+				break;
+			case VICI_LIST_START:
+				sep = (last_type != VICI_SECTION_START &&
+					   last_type != VICI_START) ? separ : "";
+				fprintf(out, "%*s%s%s%s[%s", ident, "", sep, name, assign, term);
+				ident += delta;
+				break;
+			case VICI_LIST_END:
+				ident -= delta;
+				fprintf(out, "%*s]%s", ident, "", term);
+				break;
+			case VICI_LIST_ITEM:
+				sep = (last_type != VICI_LIST_START) ? separ : "";
+				if (chunk_printable(value, NULL, ' '))
+				{
+					fprintf(out, "%*s%s%.*s%s", ident, "", sep,
+							(int)value.len, value.ptr, term);
+				}
+				else
+				{
+					fprintf(out, "%*s%s0x%+#B%s", ident, "", sep,
+							&value, term);
+				}
+				break;
+			case VICI_END:
+				fprintf(out, "}\n");
+				enumerator->destroy(enumerator);
+				return TRUE;
+		}
+		last_type = type;
+	}
+	enumerator->destroy(enumerator);
+	return FALSE;
+}
+
+METHOD(vici_message_t, destroy, void,
+	private_vici_message_t *this)
+{
+	if (this->cleanup)
+	{
+		chunk_clear(&this->encoding);
+	}
+	this->strings->destroy_function(this->strings, free);
+	free(this);
+}
+
+/**
+ * See header
+ */
+vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup)
+{
+	private_vici_message_t *this;
+
+	INIT(this,
+		.public = {
+			.create_enumerator = _create_enumerator,
+			.get_str = _get_str,
+			.vget_str = _vget_str,
+			.get_int = _get_int,
+			.vget_int = _vget_int,
+			.get_value = _get_value,
+			.vget_value = _vget_value,
+			.get_encoding = _get_encoding,
+			.parse = _parse,
+			.dump = _dump,
+			.destroy = _destroy,
+		},
+		.strings = linked_list_create(),
+		.encoding = data,
+		.cleanup = cleanup,
+	);
+
+	return &this->public;
+}
+
+/**
+ * See header
+ */
+vici_message_t *vici_message_create_from_enumerator(enumerator_t *enumerator)
+{
+	vici_builder_t *builder;
+	vici_type_t type;
+	char *name;
+	chunk_t value;
+
+	builder = vici_builder_create();
+	while (enumerator->enumerate(enumerator, &type, &name, &value))
+	{
+		switch (type)
+		{
+			case VICI_SECTION_START:
+			case VICI_LIST_START:
+				builder->add(builder, type, name);
+				continue;
+			case VICI_KEY_VALUE:
+				builder->add(builder, type, name, value);
+				continue;
+			case VICI_LIST_ITEM:
+				builder->add(builder, type, value);
+				continue;
+			case VICI_SECTION_END:
+			case VICI_LIST_END:
+			default:
+				builder->add(builder, type);
+				continue;
+			case VICI_END:
+				break;
+		}
+		break;
+	}
+	enumerator->destroy(enumerator);
+
+	return builder->finalize(builder);
+}
+
+/**
+ * See header
+ */
+vici_message_t *vici_message_create_from_args(vici_type_t type, ...)
+{
+	vici_builder_t *builder;
+	va_list args;
+	char *name;
+	chunk_t value;
+
+	builder = vici_builder_create();
+	va_start(args, type);
+	while (type != VICI_END)
+	{
+		switch (type)
+		{
+			case VICI_LIST_START:
+			case VICI_SECTION_START:
+				name = va_arg(args, char*);
+				builder->add(builder, type, name);
+				break;
+			case VICI_KEY_VALUE:
+				name = va_arg(args, char*);
+				value = va_arg(args, chunk_t);
+				builder->add(builder, type, name, value);
+				break;
+			case VICI_LIST_ITEM:
+				value = va_arg(args, chunk_t);
+				builder->add(builder, type, value);
+				break;
+			case VICI_SECTION_END:
+			case VICI_LIST_END:
+			default:
+				builder->add(builder, type);
+				break;
+		}
+		type = va_arg(args, vici_type_t);
+	}
+	va_end(args);
+	return builder->finalize(builder);
+}
diff --git a/src/libcharon/plugins/vici/vici_message.h b/src/libcharon/plugins/vici/vici_message.h
new file mode 100644
index 0000000..1a89cf8
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_message.h
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup vici_message vici_message
+ * @{ @ingroup vici_dispatcher
+ */
+
+#ifndef VICI_MESSAGE_H_
+#define VICI_MESSAGE_H_
+
+#include <library.h>
+
+typedef struct vici_message_t vici_message_t;
+typedef struct vici_parse_context_t vici_parse_context_t;
+typedef enum vici_type_t vici_type_t;
+
+/**
+ * Vici message encoding types
+ */
+enum vici_type_t {
+	/** never used in an argument list, needed by dump as initial value */
+	VICI_START =         0,
+
+	/** begin of new section, argument is section name as char* */
+	VICI_SECTION_START = 1,
+	/** end of current section, no arguments */
+	VICI_SECTION_END =   2,
+	/** key/value, arguments are key as char*, value as chunk_t */
+	VICI_KEY_VALUE =     3,
+	/** list start, argument is list name as char* */
+	VICI_LIST_START =    4,
+	/** list item, argument is item value as chunk_t */
+	VICI_LIST_ITEM =     5,
+	/** end of list, no arguments */
+	VICI_LIST_END =      6,
+
+	/** end of argument list, no arguments (never encoded) */
+	VICI_END =           7
+};
+
+/**
+ * Callback function for key/value and list items, invoked by parse().
+ *
+ * @param user		user data, as passed to parse()
+ * @param message	message currently parsing
+ * @param name		name of key or list
+ * @param value		parsed value
+ * @return			TRUE if parsed successfully
+ */
+typedef bool (*vici_value_cb_t)(void *user, vici_message_t *message,
+								char *name, chunk_t value);
+
+/**
+ * Callback function for sections, invoked by parse().
+ *
+ * @param user		user data, as passed to parse()
+ * @param message	message currently parsing
+ * @param ctx		parse context, to pass to recursive parse() invocations.
+ * @param name		name of the section
+ * @return			TRUE if parsed successfully
+ */
+typedef bool (*vici_section_cb_t)(void *user, vici_message_t *message,
+								  vici_parse_context_t *ctx, char *name);
+
+/**
+ * Names for vici encoding types
+ */
+extern enum_name_t *vici_type_names;
+
+/**
+ * Vici message representation, encoding/decoding routines.
+ */
+struct vici_message_t {
+
+	/**
+	 * Create an enumerator over message contents.
+	 *
+	 * The enumerator takes a fixed list of arguments, but depending on the
+	 * type may set not all of them. It returns VICI_END as last argument
+	 * to indicate the message end, and returns FALSE if parsing the message
+	 * failed.
+	 *
+	 * @return		enumerator over (vici_type_t, char*, chunk_t)
+	 */
+	enumerator_t* (*create_enumerator)(vici_message_t *this);
+
+	/**
+	 * Get the value of a key/value pair as a string.
+	 *
+	 * @param def	default value if not found
+	 * @param fmt	printf style format string for key, with sections
+	 * @param ...	arguments to fmt string
+	 * @return		string
+	 */
+	char* (*get_str)(vici_message_t *this, char *def, char *fmt, ...);
+
+	/**
+	 * Get the value of a key/value pair as a string, va_list variant.
+	 *
+	 * @param def	default value if not found
+	 * @param fmt	printf style format string for key, with sections
+	 * @param args	arguments to fmt string
+	 * @return		string
+	 */
+	char* (*vget_str)(vici_message_t *this, char *def, char *fmt, va_list args);
+
+	/**
+	 * Get the value of a key/value pair as integer.
+	 *
+	 * @param def	default value if not found
+	 * @param fmt	printf style format string for key, with sections
+	 * @param ...	arguments to fmt string
+	 * @return		value
+	 */
+	int (*get_int)(vici_message_t *this, int def, char *fmt, ...);
+
+	/**
+	 * Get the value of a key/value pair as integer, va_list variant
+	 *
+	 * @param def	default value if not found
+	 * @param fmt	printf style format string for key, with sections
+	 * @param args	arguments to fmt string
+	 * @return		value
+	 */
+	int (*vget_int)(vici_message_t *this, int def, char *fmt, va_list args);
+
+	/**
+	 * Get the raw value of a key/value pair.
+	 *
+	 * @param def	default value if not found
+	 * @param fmt	printf style format string for key, with sections
+	 * @param ...	arguments to fmt string
+	 * @return		value
+	 */
+	chunk_t (*get_value)(vici_message_t *this, chunk_t def, char *fmt, ...);
+
+	/**
+	 * Get the raw value of a key/value pair, va_list variant.
+	 *
+	 * @param def	default value if not found
+	 * @param fmt	printf style format string for key, with sections
+	 * @param args	arguments to fmt string
+	 * @return		value
+	 */
+	chunk_t (*vget_value)(vici_message_t *this, chunk_t def,
+						 char *fmt, va_list args);
+
+	/**
+	 * Get encoded message.
+	 *
+	 * @return		message data, points to internal data
+	 */
+	chunk_t (*get_encoding)(vici_message_t *this);
+
+	/**
+	 * Parse a message using callback functions.
+	 *
+	 * Any of the callbacks may be NULL to skip this kind of item. Callbacks are
+	 * invoked for the current section level only. To descent into sections,
+	 * call parse() from within a section callback using the provided parse
+	 * context.
+	 *
+	 * @param ctx		parse context, NULL for root level
+	 * @param section	callback invoked for each section
+	 * @param kv		callback invoked for key/value pairs
+	 * @param li		callback invoked for list items
+	 * @param user		user data to pass to callbacks
+	 * @return			TRUE if parsed successfully
+	 */
+	bool (*parse)(vici_message_t *this, vici_parse_context_t *ctx,
+				  vici_section_cb_t section, vici_value_cb_t kv,
+				  vici_value_cb_t li, void *user);
+
+	/**
+	 * Dump a message text representation to a FILE stream.
+	 *
+	 * @param label		label to print for message
+	 * @param pretty	use pretty print with indentation
+	 * @param out		FILE stream to dump to
+	 * @return			TRUE if message valid
+	 */
+	bool (*dump)(vici_message_t *this, char *label, bool pretty, FILE *out);
+
+	/**
+	 * Destroy a vici_message_t.
+	 */
+	void (*destroy)(vici_message_t *this);
+};
+
+/**
+ * Create a vici_message from encoded data.
+ *
+ * @param data			message encoding
+ * @param cleanup		TRUE to free data during
+ * @return				message representation
+ */
+vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup);
+
+/**
+ * Create a vici_message from an enumerator.
+ *
+ * The enumerator uses the same signature as the enumerator returned
+ * by create_enumerator(), and gets destroyed by this function. It should
+ * return VICI_END to close the message, return FALSE to indicate a failure.
+ *
+ * @param enumerator	enumerator over (vici_type_t, char*, chunk_t)
+ * @return				message representation, NULL on error
+ */
+vici_message_t *vici_message_create_from_enumerator(enumerator_t *enumerator);
+
+/**
+ * Create vici message from a variable argument list.
+ *
+ * @param type			first type beginning message
+ * @param ...			vici_type_t and args, terminated by VICI_END
+ * @return				message representation, NULL on error
+ */
+vici_message_t *vici_message_create_from_args(vici_type_t type, ...);
+
+/**
+ * Check if a chunk has a printable string, and print it to buf.
+ *
+ * @param chunk			chunk containing potential string
+ * @param buf			buffer to write string to
+ * @param size			size of buf
+ * @return				TRUE if printable and string written to buf
+ */
+bool vici_stringify(chunk_t chunk, char *buf, size_t size);
+
+/**
+ * Verify the occurrence of a given type for given section/list nesting
+ */
+bool vici_verify_type(vici_type_t type, u_int section, bool list);
+
+#endif /** VICI_MESSAGE_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c
new file mode 100644
index 0000000..8881fec
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_plugin.c
@@ -0,0 +1,169 @@
+/*
+ * 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 "vici_plugin.h"
+#include "vici_dispatcher.h"
+#include "vici_query.h"
+#include "vici_control.h"
+#include "vici_cred.h"
+#include "vici_config.h"
+#include "vici_attribute.h"
+#include "vici_logger.h"
+
+#include <library.h>
+#include <hydra.h>
+#include <daemon.h>
+
+typedef struct private_vici_plugin_t private_vici_plugin_t;
+
+/**
+ * Private members of vici_plugin_t
+ */
+struct private_vici_plugin_t {
+
+	/**
+	 * public functions
+	 */
+	vici_plugin_t public;
+
+	/**
+	 * Dispatcher, creating socket
+	 */
+	vici_dispatcher_t *dispatcher;
+
+	/**
+	 * Query commands
+	 */
+	vici_query_t *query;
+
+	/**
+	 * Control commands
+	 */
+	vici_control_t *control;
+
+	/**
+	 * Credential backend
+	 */
+	vici_cred_t *cred;
+
+	/**
+	 * Configuration backend
+	 */
+	vici_config_t *config;
+
+	/**
+	 * IKE attribute backend
+	 */
+	vici_attribute_t *attrs;
+
+	/**
+	 * Generic debug logger
+	 */
+	vici_logger_t *logger;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_vici_plugin_t *this)
+{
+	return "vici";
+}
+
+/**
+ * Register vici plugin features
+ */
+static bool register_vici(private_vici_plugin_t *this,
+						  plugin_feature_t *feature, bool reg, void *data)
+{
+	if (reg)
+	{
+		char *uri;
+
+		uri = lib->settings->get_str(lib->settings, "%s.plugins.vici.socket",
+									 VICI_DEFAULT_URI, lib->ns);
+		this->dispatcher = vici_dispatcher_create(uri);
+		if (this->dispatcher)
+		{
+			this->query = vici_query_create(this->dispatcher);
+			this->control = vici_control_create(this->dispatcher);
+			this->cred = vici_cred_create(this->dispatcher);
+			this->config = vici_config_create(this->dispatcher);
+			this->attrs = vici_attribute_create(this->dispatcher);
+			this->logger = vici_logger_create(this->dispatcher);
+
+			charon->backends->add_backend(charon->backends,
+										  &this->config->backend);
+			hydra->attributes->add_provider(hydra->attributes,
+											&this->attrs->provider);
+			charon->bus->add_logger(charon->bus, &this->logger->logger);
+			return TRUE;
+		}
+		return FALSE;
+	}
+	else
+	{
+		charon->bus->remove_logger(charon->bus, &this->logger->logger);
+		hydra->attributes->remove_provider(hydra->attributes,
+										   &this->attrs->provider);
+		charon->backends->remove_backend(charon->backends,
+										 &this->config->backend);
+
+		this->logger->destroy(this->logger);
+		this->attrs->destroy(this->attrs);
+		this->config->destroy(this->config);
+		this->cred->destroy(this->cred);
+		this->control->destroy(this->control);
+		this->query->destroy(this->query);
+		this->dispatcher->destroy(this->dispatcher);
+	}
+	return TRUE;
+}
+
+METHOD(plugin_t, get_features, int,
+	private_vici_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_CALLBACK((plugin_feature_callback_t)register_vici, NULL),
+			PLUGIN_PROVIDE(CUSTOM, "vici"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_vici_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *vici_plugin_create()
+{
+	private_vici_plugin_t *this;
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.reload = (void*)return_false,
+				.get_features = _get_features,
+				.destroy = _destroy,
+			},
+		},
+	);
+
+	return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/vici/vici_plugin.h b/src/libcharon/plugins/vici/vici_plugin.h
new file mode 100644
index 0000000..b4c3802
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup vici vici
+ * @ingroup cplugins
+ *
+ * @defgroup vici_plugin vici_plugin
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_PLUGIN_H_
+#define VICI_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct vici_plugin_t vici_plugin_t;
+
+/**
+ * vici plugin, the "Versatile IKE Control Interface" interface.
+ */
+struct vici_plugin_t {
+
+	/**
+	 * Implements plugin interface
+	 */
+	plugin_t plugin;
+};
+
+#endif /** VICI_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
new file mode 100644
index 0000000..54833ab
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -0,0 +1,1039 @@
+/*
+ * 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 "vici_query.h"
+#include "vici_builder.h"
+
+#include <inttypes.h>
+#include <time.h>
+#ifndef WIN32
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_MALLINFO
+#include <malloc.h>
+#endif
+
+#include <daemon.h>
+
+typedef struct private_vici_query_t private_vici_query_t;
+
+/**
+ * Private data of an vici_query_t object.
+ */
+struct private_vici_query_t {
+
+	/**
+	 * Public vici_query_t interface.
+	 */
+	vici_query_t public;
+
+	/**
+	 * Dispatcher
+	 */
+	vici_dispatcher_t *dispatcher;
+
+	/**
+	 * Daemon startup timestamp
+	 */
+	time_t uptime;
+};
+
+/**
+ * List details of a CHILD_SA
+ */
+static void list_child(private_vici_query_t *this, vici_builder_t *b,
+					   child_sa_t *child, time_t now)
+{
+	time_t t;
+	u_int64_t bytes, packets;
+	u_int16_t alg, ks;
+	proposal_t *proposal;
+	enumerator_t *enumerator;
+	traffic_selector_t *ts;
+
+	b->add_kv(b, "reqid", "%u", child->get_reqid(child));
+	b->add_kv(b, "state", "%N", child_sa_state_names, child->get_state(child));
+	b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
+	if (child->get_state(child) == CHILD_INSTALLED ||
+		child->get_state(child) == CHILD_REKEYING)
+	{
+		b->add_kv(b, "protocol", "%N", protocol_id_names,
+				  child->get_protocol(child));
+		if (child->has_encap(child))
+		{
+			b->add_kv(b, "encap", "yes");
+		}
+		b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
+		b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
+
+		if (child->get_ipcomp(child) != IPCOMP_NONE)
+		{
+			b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
+			b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
+		}
+		proposal = child->get_proposal(child);
+		if (proposal)
+		{
+			if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
+										&alg, &ks) && alg != ENCR_UNDEFINED)
+			{
+				b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
+				if (ks)
+				{
+					b->add_kv(b, "encr-keysize", "%u", ks);
+				}
+			}
+			if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
+										&alg, &ks) && alg != ENCR_UNDEFINED)
+			{
+				b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
+				if (ks)
+				{
+					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))
+			{
+				b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
+			}
+			if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
+										&alg, NULL) && alg == EXT_SEQ_NUMBERS)
+			{
+				b->add_kv(b, "esn", "1");
+			}
+		}
+
+		child->get_usestats(child, TRUE,  &t, &bytes, &packets);
+		b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
+		b->add_kv(b, "packets-in", "%" PRIu64, packets);
+		if (t)
+		{
+			b->add_kv(b, "use-in", "%"PRIu64, (u_int64_t)(now - t));
+		}
+
+		child->get_usestats(child, FALSE, &t, &bytes, &packets);
+		b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
+		b->add_kv(b, "packets-out", "%"PRIu64, packets);
+		if (t)
+		{
+			b->add_kv(b, "use-out", "%"PRIu64, (u_int64_t)(now - t));
+		}
+
+		t = child->get_lifetime(child, FALSE);
+		if (t)
+		{
+			b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
+		}
+		t = child->get_lifetime(child, TRUE);
+		if (t)
+		{
+			b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
+		}
+		t = child->get_installtime(child);
+		b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
+	}
+
+	b->begin_list(b, "local-ts");
+	enumerator = child->create_ts_enumerator(child, TRUE);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		b->add_li(b, "%R", ts);
+	}
+	enumerator->destroy(enumerator);
+	b->end_list(b /* local-ts */);
+
+	b->begin_list(b, "remote-ts");
+	enumerator = child->create_ts_enumerator(child, FALSE);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		b->add_li(b, "%R", ts);
+	}
+	enumerator->destroy(enumerator);
+	b->end_list(b /* remote-ts */);
+}
+
+/**
+ * List tasks in a specific queue
+ */
+static void list_task_queue(private_vici_query_t *this, vici_builder_t *b,
+							ike_sa_t *ike_sa, task_queue_t q, char *name)
+{
+	enumerator_t *enumerator;
+	bool has = FALSE;
+	task_t *task;
+
+	enumerator = ike_sa->create_task_enumerator(ike_sa, q);
+	while (enumerator->enumerate(enumerator, &task))
+	{
+		if (!has)
+		{
+			b->begin_list(b, name);
+			has = TRUE;
+		}
+		b->add_li(b, "%N", task_type_names, task->get_type(task));
+	}
+	enumerator->destroy(enumerator);
+	if (has)
+	{
+		b->end_list(b);
+	}
+}
+
+/**
+ * List details of an IKE_SA
+ */
+static void list_ike(private_vici_query_t *this, vici_builder_t *b,
+					 ike_sa_t *ike_sa, time_t now)
+{
+	time_t t;
+	ike_sa_id_t *id;
+	identification_t *eap;
+	proposal_t *proposal;
+	u_int16_t alg, ks;
+
+	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));
+	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));
+	b->add_kv(b, "remote-id", "%Y", ike_sa->get_other_id(ike_sa));
+
+	eap = ike_sa->get_other_eap_id(ike_sa);
+
+	if (!eap->equals(eap, ike_sa->get_other_id(ike_sa)))
+	{
+		if (ike_sa->get_version(ike_sa) == IKEV1)
+		{
+			b->add_kv(b, "remote-xauth-id", "%Y", eap);
+		}
+		else
+		{
+			b->add_kv(b, "remote-eap-id", "%Y", eap);
+		}
+	}
+
+	id = ike_sa->get_id(ike_sa);
+	if (id->is_initiator(id))
+	{
+		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));
+
+	proposal = ike_sa->get_proposal(ike_sa);
+	if (proposal)
+	{
+		if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &ks))
+		{
+			b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
+			if (ks)
+			{
+				b->add_kv(b, "encr-keysize", "%u", ks);
+			}
+		}
+		if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, &ks))
+		{
+			b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
+			if (ks)
+			{
+				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))
+		{
+			b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
+		}
+	}
+
+	if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
+	{
+		t = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
+		b->add_kv(b, "established", "%"PRId64, (int64_t)(now - t));
+		t = ike_sa->get_statistic(ike_sa, STAT_REKEY);
+		if (t)
+		{
+			b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
+		}
+		t = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
+		if (t)
+		{
+			b->add_kv(b, "reauth-time", "%"PRId64, (int64_t)(t - now));
+		}
+	}
+
+	list_task_queue(this, b, ike_sa, TASK_QUEUE_QUEUED, "tasks-queued");
+	list_task_queue(this, b, ike_sa, TASK_QUEUE_ACTIVE, "tasks-active");
+	list_task_queue(this, b, ike_sa, TASK_QUEUE_PASSIVE, "tasks-passive");
+}
+
+CALLBACK(list_sas, vici_message_t*,
+	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+	vici_builder_t *b;
+	enumerator_t *isas, *csas;
+	ike_sa_t *ike_sa;
+	child_sa_t *child_sa;
+	time_t now;
+	char *ike;
+	u_int ike_id;
+	bool bl;
+
+	bl = request->get_str(request, NULL, "noblock") == NULL;
+	ike = request->get_str(request, NULL, "ike");
+	ike_id = request->get_int(request, 0, "ike-id");
+
+	isas = charon->controller->create_ike_sa_enumerator(charon->controller, bl);
+	while (isas->enumerate(isas, &ike_sa))
+	{
+		if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
+		{
+			continue;
+		}
+		if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
+		{
+			continue;
+		}
+
+		now = time_monotonic(NULL);
+
+		b = vici_builder_create();
+		b->begin_section(b, ike_sa->get_name(ike_sa));
+
+		list_ike(this, b, ike_sa, now);
+
+		b->begin_section(b, "child-sas");
+		csas = ike_sa->create_child_sa_enumerator(ike_sa);
+		while (csas->enumerate(csas, &child_sa))
+		{
+			b->begin_section(b, child_sa->get_name(child_sa));
+			list_child(this, b, child_sa, now);
+			b->end_section(b);
+		}
+		csas->destroy(csas);
+		b->end_section(b /* child-sas */ );
+
+		b->end_section(b);
+
+		this->dispatcher->raise_event(this->dispatcher, "list-sa", id,
+									  b->finalize(b));
+	}
+	isas->destroy(isas);
+
+	b = vici_builder_create();
+	return b->finalize(b);
+}
+
+/**
+ * Raise a list-policy event for given CHILD_SA
+ */
+static void raise_policy(private_vici_query_t *this, u_int id, child_sa_t *child)
+{
+	enumerator_t *enumerator;
+	traffic_selector_t *ts;
+	vici_builder_t *b;
+
+	b = vici_builder_create();
+	b->begin_section(b, child->get_name(child));
+
+	b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
+
+	b->begin_list(b, "local-ts");
+	enumerator = child->create_ts_enumerator(child, TRUE);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		b->add_li(b, "%R", ts);
+	}
+	enumerator->destroy(enumerator);
+	b->end_list(b /* local-ts */);
+
+	b->begin_list(b, "remote-ts");
+	enumerator = child->create_ts_enumerator(child, FALSE);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		b->add_li(b, "%R", ts);
+	}
+	enumerator->destroy(enumerator);
+	b->end_list(b /* remote-ts */);
+
+	b->end_section(b);
+
+	this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
+								  b->finalize(b));
+}
+
+/**
+ * Raise a list-policy event for given CHILD_SA config
+ */
+static void raise_policy_cfg(private_vici_query_t *this, u_int id,
+							 child_cfg_t *cfg)
+{
+	enumerator_t *enumerator;
+	linked_list_t *list;
+	traffic_selector_t *ts;
+	vici_builder_t *b;
+
+	b = vici_builder_create();
+	b->begin_section(b, cfg->get_name(cfg));
+
+	b->add_kv(b, "mode", "%N", ipsec_mode_names, cfg->get_mode(cfg));
+
+	b->begin_list(b, "local-ts");
+	list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL);
+	enumerator = list->create_enumerator(list);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		b->add_li(b, "%R", ts);
+	}
+	enumerator->destroy(enumerator);
+	list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+	b->end_list(b /* local-ts */);
+
+	b->begin_list(b, "remote-ts");
+	list = cfg->get_traffic_selectors(cfg, FALSE, NULL, NULL);
+	enumerator = list->create_enumerator(list);
+	while (enumerator->enumerate(enumerator, &ts))
+	{
+		b->add_li(b, "%R", ts);
+	}
+	enumerator->destroy(enumerator);
+	list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+	b->end_list(b /* remote-ts */);
+
+	b->end_section(b);
+
+	this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
+								  b->finalize(b));
+}
+
+CALLBACK(list_policies, vici_message_t*,
+	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+	enumerator_t *enumerator;
+	vici_builder_t *b;
+	child_sa_t *child_sa;
+	child_cfg_t *child_cfg;
+	bool drop, pass, trap;
+	char *child;
+
+	drop = request->get_str(request, NULL, "drop") != NULL;
+	pass = request->get_str(request, NULL, "pass") != NULL;
+	trap = request->get_str(request, NULL, "trap") != NULL;
+	child = request->get_str(request, NULL, "child");
+
+	if (trap)
+	{
+		enumerator = charon->traps->create_enumerator(charon->traps);
+		while (enumerator->enumerate(enumerator, NULL, &child_sa))
+		{
+			if (child && !streq(child, child_sa->get_name(child_sa)))
+			{
+				continue;
+			}
+			raise_policy(this, id, child_sa);
+		}
+		enumerator->destroy(enumerator);
+	}
+
+	if (drop || pass)
+	{
+		enumerator = charon->shunts->create_enumerator(charon->shunts);
+		while (enumerator->enumerate(enumerator, &child_cfg))
+		{
+			if (child && !streq(child, child_cfg->get_name(child_cfg)))
+			{
+				continue;
+			}
+			switch (child_cfg->get_mode(child_cfg))
+			{
+				case MODE_DROP:
+					if (drop)
+					{
+						raise_policy_cfg(this, id, child_cfg);
+					}
+					break;
+				case MODE_PASS:
+					if (pass)
+					{
+						raise_policy_cfg(this, id, child_cfg);
+					}
+					break;
+				default:
+					break;
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+
+	b = vici_builder_create();
+	return b->finalize(b);
+}
+
+/**
+ * Build sections for auth configs, local or remote
+ */
+static void build_auth_cfgs(peer_cfg_t *peer_cfg, bool local, vici_builder_t *b)
+{
+	enumerator_t *enumerator, *rules;
+	auth_rule_t rule;
+	auth_cfg_t *auth;
+	union {
+		uintptr_t u;
+		identification_t *id;
+		certificate_t *cert;
+		char *str;
+	} v;
+
+	enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
+	while (enumerator->enumerate(enumerator, &auth))
+	{
+		b->begin_section(b, local ? "local" : "remote");
+
+		rules = auth->create_enumerator(auth);
+		while (rules->enumerate(rules, &rule, &v))
+		{
+			switch (rule)
+			{
+				case AUTH_RULE_AUTH_CLASS:
+					b->add_kv(b, "class", "%N", auth_class_names, v.u);
+					break;
+				case AUTH_RULE_EAP_TYPE:
+					b->add_kv(b, "eap-type", "%N", eap_type_names, v.u);
+					break;
+				case AUTH_RULE_EAP_VENDOR:
+					b->add_kv(b, "eap-vendor", "%u", v.u);
+					break;
+				case AUTH_RULE_XAUTH_BACKEND:
+					b->add_kv(b, "xauth", "%s", v.str);
+					break;
+				case AUTH_RULE_CRL_VALIDATION:
+					b->add_kv(b, "revocation", "%N", cert_validation_names, v.u);
+					break;
+				case AUTH_RULE_IDENTITY:
+					b->add_kv(b, "id", "%Y", v.id);
+					break;
+				case AUTH_RULE_AAA_IDENTITY:
+					b->add_kv(b, "aaa_id", "%Y", v.id);
+					break;
+				case AUTH_RULE_EAP_IDENTITY:
+					b->add_kv(b, "eap_id", "%Y", v.id);
+					break;
+				case AUTH_RULE_XAUTH_IDENTITY:
+					b->add_kv(b, "xauth_id", "%Y", v.id);
+					break;
+				default:
+					break;
+			}
+		}
+		rules->destroy(rules);
+
+		b->begin_list(b, "groups");
+		rules = auth->create_enumerator(auth);
+		while (rules->enumerate(rules, &rule, &v))
+		{
+			if (rule == AUTH_RULE_GROUP)
+			{
+				b->add_li(b, "%Y", v.id);
+			}
+		}
+		rules->destroy(rules);
+		b->end_list(b);
+
+		b->begin_list(b, "certs");
+		rules = auth->create_enumerator(auth);
+		while (rules->enumerate(rules, &rule, &v))
+		{
+			if (rule == AUTH_RULE_SUBJECT_CERT)
+			{
+				b->add_li(b, "%Y", v.cert->get_subject(v.cert));
+			}
+		}
+		rules->destroy(rules);
+		b->end_list(b);
+
+		b->begin_list(b, "cacerts");
+		rules = auth->create_enumerator(auth);
+		while (rules->enumerate(rules, &rule, &v))
+		{
+			if (rule == AUTH_RULE_CA_CERT)
+			{
+				b->add_li(b, "%Y", v.cert->get_subject(v.cert));
+			}
+		}
+		rules->destroy(rules);
+		b->end_list(b);
+
+		b->end_section(b);
+	}
+	enumerator->destroy(enumerator);
+}
+
+CALLBACK(list_conns, vici_message_t*,
+	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+	enumerator_t *enumerator, *tokens, *selectors, *children;
+	peer_cfg_t *peer_cfg;
+	ike_cfg_t *ike_cfg;
+	child_cfg_t *child_cfg;
+	char *ike, *str;
+	linked_list_t *list;
+	traffic_selector_t *ts;
+	vici_builder_t *b;
+
+	ike = request->get_str(request, NULL, "ike");
+
+	enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
+											NULL, NULL, NULL, NULL, IKE_ANY);
+	while (enumerator->enumerate(enumerator, &peer_cfg))
+	{
+		if (ike && !streq(ike, peer_cfg->get_name(peer_cfg)))
+		{
+			continue;
+		}
+
+		b = vici_builder_create();
+		b->begin_section(b, peer_cfg->get_name(peer_cfg));
+
+		ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
+
+		b->begin_list(b, "local_addrs");
+		str = ike_cfg->get_my_addr(ike_cfg);
+		tokens = enumerator_create_token(str, ",", " ");
+		while (tokens->enumerate(tokens, &str))
+		{
+			b->add_li(b, "%s", str);
+		}
+		tokens->destroy(tokens);
+		b->end_list(b);
+
+		b->begin_list(b, "remote_addrs");
+		str = ike_cfg->get_other_addr(ike_cfg);
+		tokens = enumerator_create_token(str, ",", " ");
+		while (tokens->enumerate(tokens, &str))
+		{
+			b->add_li(b, "%s", str);
+		}
+		tokens->destroy(tokens);
+		b->end_list(b);
+
+		b->add_kv(b, "version", "%N", ike_version_names,
+			peer_cfg->get_ike_version(peer_cfg));
+
+		build_auth_cfgs(peer_cfg, TRUE, b);
+		build_auth_cfgs(peer_cfg, FALSE, b);
+
+		b->begin_section(b, "children");
+
+		children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+		while (children->enumerate(children, &child_cfg))
+		{
+			b->begin_section(b, child_cfg->get_name(child_cfg));
+
+			b->add_kv(b, "mode", "%N", ipsec_mode_names,
+				child_cfg->get_mode(child_cfg));
+
+			b->begin_list(b, "local-ts");
+			list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+			selectors = list->create_enumerator(list);
+			while (selectors->enumerate(selectors, &ts))
+			{
+				b->add_li(b, "%R", ts);
+			}
+			selectors->destroy(selectors);
+			list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+			b->end_list(b /* local-ts */);
+
+			b->begin_list(b, "remote-ts");
+			list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
+			selectors = list->create_enumerator(list);
+			while (selectors->enumerate(selectors, &ts))
+			{
+				b->add_li(b, "%R", ts);
+			}
+			selectors->destroy(selectors);
+			list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+			b->end_list(b /* remote-ts */);
+
+			b->end_section(b);
+		}
+		children->destroy(children);
+
+		b->end_section(b); /* children */
+
+		b->end_section(b); /* name */
+
+		this->dispatcher->raise_event(this->dispatcher, "list-conn", id,
+									  b->finalize(b));
+	}
+	enumerator->destroy(enumerator);
+
+	b = vici_builder_create();
+	return b->finalize(b);
+}
+
+/**
+ * Do we have a private key for given certificate
+ */
+static bool has_privkey(private_vici_query_t *this, certificate_t *cert)
+{
+	private_key_t *private;
+	public_key_t *public;
+	identification_t *keyid;
+	chunk_t chunk;
+	bool found = FALSE;
+
+	public = cert->get_public_key(cert);
+	if (public)
+	{
+		if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
+		{
+			keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+			private = lib->credmgr->get_private(lib->credmgr,
+								public->get_type(public), keyid, NULL);
+			if (private)
+			{
+				found = TRUE;
+				private->destroy(private);
+			}
+			keyid->destroy(keyid);
+		}
+		public->destroy(public);
+	}
+	return found;
+}
+
+CALLBACK(list_certs, vici_message_t*,
+	private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+	enumerator_t *enumerator, *added;
+	linked_list_t *list;
+	certificate_t *cert, *current;
+	chunk_t encoding;
+	identification_t *subject = NULL;
+	int type;
+	vici_builder_t *b;
+	bool found;
+	char *str;
+
+	str = request->get_str(request, "ANY", "type");
+	if (!enum_from_name(certificate_type_names, str, &type))
+	{
+		b = vici_builder_create();
+		return b->finalize(b);
+	}
+	str = request->get_str(request, NULL, "subject");
+	if (str)
+	{
+		subject = identification_create_from_string(str);
+	}
+
+	list = linked_list_create();
+	enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+												type, KEY_ANY, subject, FALSE);
+	while (enumerator->enumerate(enumerator, &cert))
+	{
+		found = FALSE;
+		added = list->create_enumerator(list);
+		while (added->enumerate(added, &current))
+		{
+			if (current->equals(current, cert))
+			{
+				found = TRUE;
+				break;
+			}
+		}
+		added->destroy(added);
+
+		if (!found && cert->get_encoding(cert, CERT_ASN1_DER, &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, "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));
+			list->insert_last(list, cert->get_ref(cert));
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	list->destroy_offset(list, offsetof(certificate_t, destroy));
+	DESTROY_IF(subject);
+
+	b = vici_builder_create();
+	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);
+
+#ifdef WIN32
+	{
+		OSVERSIONINFOEX osvie;
+
+		memset(&osvie, 0, sizeof(osvie));
+		osvie.dwOSVersionInfoSize = sizeof(osvie);
+
+		if (GetVersionEx((LPOSVERSIONINFO)&osvie))
+		{
+			b->add_kv(b, "sysname", "Windows %s",
+				osvie.wProductType == VER_NT_WORKSTATION ? "Client" : "Server");
+			b->add_kv(b, "release", "%d.%d.%d (SP %d.%d)",
+				osvie.dwMajorVersion, osvie.dwMinorVersion, osvie.dwBuildNumber,
+				osvie.wServicePackMajor, osvie.wServicePackMinor);
+			b->add_kv(b, "machine", "%s",
+#ifdef WIN64
+				"x86_64");
+#else
+				"x86");
+#endif /* !WIN64 */
+		}
+	}
+#else /* !WIN32 */
+	{
+		struct utsname utsname;
+
+		if (uname(&utsname) == 0)
+		{
+			b->add_kv(b, "sysname", "%s", utsname.sysname);
+			b->add_kv(b, "release", "%s", utsname.release);
+			b->add_kv(b, "machine", "%s", utsname.machine);
+		}
+	}
+#endif /* !WIN32 */
+	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)
+{
+	vici_builder_t *b;
+	enumerator_t *enumerator;
+	plugin_t *plugin;
+	time_t since, now;
+	int i;
+
+	b = vici_builder_create();
+
+	now = time_monotonic(NULL);
+	since = time(NULL) - (now - this->uptime);
+
+	b->begin_section(b, "uptime");
+	b->add_kv(b, "running", "%V", &now, &this->uptime);
+	b->add_kv(b, "since", "%T", &since, FALSE);
+	b->end_section(b);
+
+	b->begin_section(b, "workers");
+	b->add_kv(b, "total", "%d",
+		lib->processor->get_total_threads(lib->processor));
+	b->add_kv(b, "idle", "%d",
+		lib->processor->get_idle_threads(lib->processor));
+	b->begin_section(b, "active");
+	for (i = 0; i < JOB_PRIO_MAX; i++)
+	{
+		b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
+			lib->processor->get_working_threads(lib->processor, i));
+	}
+	b->end_section(b);
+	b->end_section(b);
+
+	b->begin_section(b, "queues");
+	for (i = 0; i < JOB_PRIO_MAX; i++)
+	{
+		b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
+			lib->processor->get_job_load(lib->processor, i));
+	}
+	b->end_section(b);
+
+	b->add_kv(b, "scheduled", "%d",
+		lib->scheduler->get_job_load(lib->scheduler));
+
+	b->begin_section(b, "ikesas");
+	b->add_kv(b, "total", "%u",
+		charon->ike_sa_manager->get_count(charon->ike_sa_manager));
+	b->add_kv(b, "half-open", "%u",
+		charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
+													NULL));
+	b->end_section(b);
+
+	b->begin_list(b, "plugins");
+	enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+	while (enumerator->enumerate(enumerator, &plugin, NULL))
+	{
+		b->add_li(b, "%s", plugin->get_name(plugin));
+	}
+	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];
+		int i, count;
+		char buf[16];
+		size_t total = 0;
+		int allocs = 0;
+
+		b->begin_section(b, "mem");
+		count = GetProcessHeaps(countof(heaps), heaps);
+		for (i = 0; i < count; i++)
+		{
+			PROCESS_HEAP_ENTRY entry = {};
+			size_t heap_total = 0;
+			int heap_allocs = 0;
+
+			if (HeapLock(heaps[i]))
+			{
+				while (HeapWalk(heaps[i], &entry))
+				{
+					if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
+					{
+						heap_total += entry.cbData;
+						heap_allocs++;
+					}
+				}
+				lasterr = GetLastError();
+				HeapUnlock(heaps[i]);
+			}
+			if (lasterr != ERROR_NO_MORE_ITEMS)
+			{
+				break;
+			}
+			snprintf(buf, sizeof(buf), "heap-%d", i);
+			b->begin_section(b, buf);
+			b->add_kv(b, "total", "%zu", heap_total);
+			b->add_kv(b, "allocs", "%d", heap_allocs);
+			b->end_section(b);
+
+			total += heap_total;
+			allocs += heap_allocs;
+		}
+		if (lasterr == ERROR_NO_MORE_ITEMS)
+		{
+			b->add_kv(b, "total", "%zu", total);
+			b->add_kv(b, "allocs", "%d", allocs);
+		}
+		b->end_section(b);
+	}
+#endif
+
+#ifdef HAVE_MALLINFO
+	{
+		struct mallinfo mi = mallinfo();
+
+		b->begin_section(b, "mallinfo");
+		b->add_kv(b, "sbrk", "%d", mi.arena);
+		b->add_kv(b, "mmap", "%d", mi.hblkhd);
+		b->add_kv(b, "used", "%d", mi.uordblks);
+		b->add_kv(b, "free", "%d", mi.fordblks);
+		b->end_section(b);
+	}
+#endif /* HAVE_MALLINFO */
+
+	return b->finalize(b);
+}
+
+static void manage_command(private_vici_query_t *this,
+						   char *name, vici_command_cb_t cb, bool reg)
+{
+	this->dispatcher->manage_command(this->dispatcher, name,
+									 reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_query_t *this, bool reg)
+{
+	this->dispatcher->manage_event(this->dispatcher, "list-sa", reg);
+	this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
+	this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
+	this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
+	manage_command(this, "list-sas", list_sas, 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, "version", version, reg);
+	manage_command(this, "stats", stats, reg);
+}
+
+METHOD(vici_query_t, destroy, void,
+	private_vici_query_t *this)
+{
+	manage_commands(this, FALSE);
+	free(this);
+}
+
+/**
+ * See header
+ */
+vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
+{
+	private_vici_query_t *this;
+
+	INIT(this,
+		.public = {
+			.destroy = _destroy,
+		},
+		.dispatcher = dispatcher,
+		.uptime = time_monotonic(NULL),
+	);
+
+	manage_commands(this, TRUE);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_query.h b/src/libcharon/plugins/vici/vici_query.h
new file mode 100644
index 0000000..da72b14
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_query.h
@@ -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.
+ */
+
+/**
+ * @defgroup vici_query vici_query
+ * @{ @ingroup vici
+ */
+
+#include "vici_dispatcher.h"
+
+#ifndef VICI_QUERY_H_
+#define VICI_QUERY_H_
+
+typedef struct vici_query_t vici_query_t;
+
+/**
+ * Query helper, provides various commands to query/list daemon info.
+ */
+struct vici_query_t {
+
+	/**
+	 * Destroy a vici_query_t.
+	 */
+	void (*destroy)(vici_query_t *this);
+};
+
+/**
+ * Create a vici_query instance.
+ *
+ * @param dispatcher		dispatcher to receive requests from
+ * @return					query handler
+ */
+vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher);
+
+#endif /** VICI_QUERY_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_socket.c b/src/libcharon/plugins/vici/vici_socket.c
new file mode 100644
index 0000000..9167728
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_socket.c
@@ -0,0 +1,679 @@
+/*
+ * 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 "vici_socket.h"
+
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+#include <threading/thread.h>
+#include <collections/array.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+#include <errno.h>
+#include <string.h>
+
+typedef struct private_vici_socket_t private_vici_socket_t;
+
+/**
+ * Private members of vici_socket_t
+ */
+struct private_vici_socket_t {
+
+	/**
+	 * public functions
+	 */
+	vici_socket_t public;
+
+	/**
+	 * Inbound message callback
+	 */
+	vici_inbound_cb_t inbound;
+
+	/**
+	 * Client connect callback
+	 */
+	vici_connect_cb_t connect;
+
+	/**
+	 * Client disconnect callback
+	 */
+	vici_disconnect_cb_t disconnect;
+
+	/**
+	 * Next client connection identifier
+	 */
+	u_int nextid;
+
+	/**
+	 * User data for callbacks
+	 */
+	void *user;
+
+	/**
+	 * Service accepting vici connections
+	 */
+	stream_service_t *service;
+
+	/**
+	 * Client connections, as entry_t
+	 */
+	linked_list_t *connections;
+
+	/**
+	 * mutex for client connections
+	 */
+	mutex_t *mutex;
+};
+
+/**
+ * Data to securely reference an entry
+ */
+typedef struct {
+	/* reference to socket instance */
+	private_vici_socket_t *this;
+	/** connection identifier of entry */
+	u_int id;
+} entry_selector_t;
+
+/**
+ * Partially processed message
+ */
+typedef struct {
+	/** bytes of length header sent/received */
+	u_char hdrlen;
+	/** bytes of length header */
+	char hdr[sizeof(u_int32_t)];
+	/** send/receive buffer on heap */
+	chunk_t buf;
+	/** bytes sent/received in buffer */
+	u_int32_t done;
+} msg_buf_t;
+
+/**
+ * Client connection entry
+ */
+typedef struct {
+	/** reference to socket */
+	private_vici_socket_t *this;
+	/** associated stream */
+	stream_t *stream;
+	/** queued messages to send, as msg_buf_t pointers */
+	array_t *out;
+	/** input message buffer */
+	msg_buf_t in;
+	/** queued input messages to process, as chunk_t */
+	array_t *queue;
+	/** do we have job processing input queue? */
+	bool has_processor;
+	/** client connection identifier */
+	u_int id;
+	/** any users reading over this connection? */
+	int readers;
+	/** any users writing over this connection? */
+	int writers;
+	/** condvar to wait for usage  */
+	condvar_t *cond;
+} entry_t;
+
+/**
+ * Destroy an connection entry
+ */
+CALLBACK(destroy_entry, void,
+	entry_t *entry)
+{
+	msg_buf_t *out;
+	chunk_t chunk;
+
+	entry->stream->destroy(entry->stream);
+	entry->this->disconnect(entry->this->user, entry->id);
+	entry->cond->destroy(entry->cond);
+
+	while (array_remove(entry->out, ARRAY_TAIL, &out))
+	{
+		chunk_clear(&out->buf);
+		free(out);
+	}
+	array_destroy(entry->out);
+	while (array_remove(entry->queue, ARRAY_TAIL, &chunk))
+	{
+		chunk_clear(&chunk);
+	}
+	array_destroy(entry->queue);
+	chunk_clear(&entry->in.buf);
+	free(entry);
+}
+
+/**
+ * Find entry by stream (if given) or id, claim use
+ */
+static entry_t* find_entry(private_vici_socket_t *this, stream_t *stream,
+						   u_int id, bool reader, bool writer)
+{
+	enumerator_t *enumerator;
+	entry_t *entry, *found = NULL;
+	bool candidate = TRUE;
+
+	this->mutex->lock(this->mutex);
+	while (candidate && !found)
+	{
+		candidate = FALSE;
+		enumerator = this->connections->create_enumerator(this->connections);
+		while (enumerator->enumerate(enumerator, &entry))
+		{
+			if (stream)
+			{
+				if (entry->stream != stream)
+				{
+					continue;
+				}
+			}
+			else
+			{
+				if (entry->id != id)
+				{
+					continue;
+				}
+			}
+			candidate = TRUE;
+
+			if ((reader && entry->readers) ||
+				(writer && entry->writers))
+			{
+				entry->cond->wait(entry->cond, this->mutex);
+				break;
+			}
+			if (reader)
+			{
+				entry->readers++;
+			}
+			if (writer)
+			{
+				entry->writers++;
+			}
+			found = entry;
+			break;
+		}
+		enumerator->destroy(enumerator);
+	}
+	this->mutex->unlock(this->mutex);
+
+	return found;
+}
+
+/**
+ * Remove entry by id, claim use
+ */
+static entry_t* remove_entry(private_vici_socket_t *this, u_int id)
+{
+	enumerator_t *enumerator;
+	entry_t *entry, *found = NULL;
+	bool candidate = TRUE;
+
+	this->mutex->lock(this->mutex);
+	while (candidate && !found)
+	{
+		candidate = FALSE;
+		enumerator = this->connections->create_enumerator(this->connections);
+		while (enumerator->enumerate(enumerator, &entry))
+		{
+			if (entry->id == id)
+			{
+				candidate = TRUE;
+				if (entry->readers || entry->writers)
+				{
+					entry->cond->wait(entry->cond, this->mutex);
+					break;
+				}
+				this->connections->remove_at(this->connections, enumerator);
+				found = entry;
+				break;
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+	this->mutex->unlock(this->mutex);
+
+	return found;
+}
+
+/**
+ * Release a claimed entry
+ */
+static void put_entry(private_vici_socket_t *this, entry_t *entry,
+					  bool reader, bool writer)
+{
+	this->mutex->lock(this->mutex);
+	if (reader)
+	{
+		entry->readers--;
+	}
+	if (writer)
+	{
+		entry->writers--;
+	}
+	entry->cond->signal(entry->cond);
+	this->mutex->unlock(this->mutex);
+}
+
+/**
+ * Asynchronous callback to disconnect client
+ */
+CALLBACK(disconnect_async, job_requeue_t,
+	entry_selector_t *sel)
+{
+	entry_t *entry;
+
+	entry = remove_entry(sel->this, sel->id);
+	if (entry)
+	{
+		destroy_entry(entry);
+	}
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Disconnect a connected client
+ */
+static void disconnect(private_vici_socket_t *this, u_int id)
+{
+	entry_selector_t *sel;
+
+	INIT(sel,
+		.this = this,
+		.id = id,
+	);
+
+	lib->processor->queue_job(lib->processor,
+			(job_t*)callback_job_create(disconnect_async, sel, free, NULL));
+}
+
+/**
+ * Write queued output data
+ */
+static bool do_write(private_vici_socket_t *this, entry_t *entry,
+					 stream_t *stream)
+{
+	msg_buf_t *out;
+	ssize_t len;
+
+	while (array_get(entry->out, ARRAY_HEAD, &out))
+	{
+		/* write header */
+		while (out->hdrlen < sizeof(out->hdr))
+		{
+			len = stream->write(stream, out->hdr + out->hdrlen,
+								sizeof(out->hdr) - out->hdrlen, FALSE);
+			if (len == 0)
+			{
+				return FALSE;
+			}
+			if (len < 0)
+			{
+				if (errno == EWOULDBLOCK)
+				{
+					return TRUE;
+				}
+				DBG1(DBG_CFG, "vici header write error: %s", strerror(errno));
+				return FALSE;
+			}
+			out->hdrlen += len;
+		}
+
+		/* write buffer buffer */
+		while (out->buf.len > out->done)
+		{
+			len = stream->write(stream, out->buf.ptr + out->done,
+								out->buf.len - out->done, FALSE);
+			if (len == 0)
+			{
+				DBG1(DBG_CFG, "premature vici disconnect");
+				return FALSE;
+			}
+			if (len < 0)
+			{
+				if (errno == EWOULDBLOCK)
+				{
+					return TRUE;
+				}
+				DBG1(DBG_CFG, "vici write error: %s", strerror(errno));
+				return FALSE;
+			}
+			out->done += len;
+		}
+
+		if (array_remove(entry->out, ARRAY_HEAD, &out))
+		{
+			chunk_clear(&out->buf);
+			free(out);
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * Send pending messages
+ */
+CALLBACK(on_write, bool,
+	private_vici_socket_t *this, stream_t *stream)
+{
+	entry_t *entry;
+	bool ret = FALSE;
+
+	entry = find_entry(this, stream, 0, FALSE, TRUE);
+	if (entry)
+	{
+		ret = do_write(this, entry, stream);
+		if (ret)
+		{
+			/* unregister if we have no more messages to send */
+			ret = array_count(entry->out) != 0;
+		}
+		else
+		{
+			disconnect(entry->this, entry->id);
+		}
+		put_entry(this, entry, FALSE, TRUE);
+	}
+
+	return ret;
+}
+
+/**
+ * Read in available header with data, non-blocking cumulating to buffer
+ */
+static bool do_read(private_vici_socket_t *this, entry_t *entry,
+					stream_t *stream)
+{
+	u_int32_t msglen;
+	ssize_t len;
+
+	/* assemble the length header first */
+	while (entry->in.hdrlen < sizeof(entry->in.hdr))
+	{
+		len = stream->read(stream, entry->in.hdr + entry->in.hdrlen,
+						   sizeof(entry->in.hdr) - entry->in.hdrlen, FALSE);
+		if (len == 0)
+		{
+			return FALSE;
+		}
+		if (len < 0)
+		{
+			if (errno == EWOULDBLOCK)
+			{
+				return TRUE;
+			}
+			DBG1(DBG_CFG, "vici header read error: %s", strerror(errno));
+			return FALSE;
+		}
+		entry->in.hdrlen += len;
+		if (entry->in.hdrlen == sizeof(entry->in.hdr))
+		{
+			msglen = untoh32(entry->in.hdr);
+			if (msglen > VICI_MESSAGE_SIZE_MAX)
+			{
+				DBG1(DBG_CFG, "vici message length %u exceeds %u bytes limit, "
+					 "ignored", msglen, VICI_MESSAGE_SIZE_MAX);
+				return FALSE;
+			}
+			/* header complete, continue with data */
+			entry->in.buf = chunk_alloc(msglen);
+		}
+	}
+
+	/* assemble buffer */
+	while (entry->in.buf.len > entry->in.done)
+	{
+		len = stream->read(stream, entry->in.buf.ptr + entry->in.done,
+						   entry->in.buf.len - entry->in.done, FALSE);
+		if (len == 0)
+		{
+			DBG1(DBG_CFG, "premature vici disconnect");
+			return FALSE;
+		}
+		if (len < 0)
+		{
+			if (errno == EWOULDBLOCK)
+			{
+				return TRUE;
+			}
+			DBG1(DBG_CFG, "vici read error: %s", strerror(errno));
+			return FALSE;
+		}
+		entry->in.done += len;
+	}
+
+	return TRUE;
+}
+
+/**
+ * Callback processing incoming requestes in strict order
+ */
+CALLBACK(process_queue, job_requeue_t,
+	entry_selector_t *sel)
+{
+	entry_t *entry;
+	chunk_t chunk;
+	bool found;
+	u_int id;
+
+	while (TRUE)
+	{
+		entry = find_entry(sel->this, NULL, sel->id, TRUE, FALSE);
+		if (!entry)
+		{
+			break;
+		}
+
+		found = array_remove(entry->queue, ARRAY_HEAD, &chunk);
+		if (!found)
+		{
+			entry->has_processor = FALSE;
+		}
+		id = entry->id;
+		put_entry(sel->this, entry, TRUE, FALSE);
+		if (!found)
+		{
+			break;
+		}
+
+		thread_cleanup_push(free, chunk.ptr);
+		sel->this->inbound(sel->this->user, id, chunk);
+		thread_cleanup_pop(TRUE);
+	}
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Process incoming messages
+ */
+CALLBACK(on_read, bool,
+	private_vici_socket_t *this, stream_t *stream)
+{
+	entry_selector_t *sel;
+	entry_t *entry;
+	bool ret = FALSE;
+
+	entry = find_entry(this, stream, 0, TRUE, FALSE);
+	if (entry)
+	{
+		ret = do_read(this, entry, stream);
+		if (!ret)
+		{
+			disconnect(this, entry->id);
+		}
+		else if (entry->in.hdrlen == sizeof(entry->in.hdr) &&
+				 entry->in.buf.len == entry->in.done)
+		{
+			array_insert(entry->queue, ARRAY_TAIL, &entry->in.buf);
+			entry->in.buf = chunk_empty;
+			entry->in.hdrlen = entry->in.done = 0;
+
+			if (!entry->has_processor)
+			{
+				INIT(sel,
+					.this = this,
+					.id = entry->id,
+				);
+				lib->processor->queue_job(lib->processor,
+							(job_t*)callback_job_create(process_queue,
+														sel, free, NULL));
+				entry->has_processor = TRUE;
+			}
+		}
+		put_entry(this, entry, TRUE, FALSE);
+	}
+
+	return ret;
+}
+
+/**
+ * Process connection request
+ */
+CALLBACK(on_accept, bool,
+	private_vici_socket_t *this, stream_t *stream)
+{
+	entry_t *entry;
+	u_int id;
+
+	id = ref_get(&this->nextid);
+
+	INIT(entry,
+		.this = this,
+		.stream = stream,
+		.id = id,
+		.out = array_create(0, 0),
+		.queue = array_create(sizeof(chunk_t), 0),
+		.cond = condvar_create(CONDVAR_TYPE_DEFAULT),
+		.readers = 1,
+	);
+
+	this->mutex->lock(this->mutex);
+	this->connections->insert_last(this->connections, entry);
+	this->mutex->unlock(this->mutex);
+
+	stream->on_read(stream, on_read, this);
+
+	put_entry(this, entry, TRUE, FALSE);
+
+	this->connect(this->user, id);
+
+	return TRUE;
+}
+
+/**
+ * Async callback to enable writer
+ */
+CALLBACK(enable_writer, job_requeue_t,
+	entry_selector_t *sel)
+{
+	entry_t *entry;
+
+	entry = find_entry(sel->this, NULL, sel->id, FALSE, TRUE);
+	if (entry)
+	{
+		entry->stream->on_write(entry->stream, on_write, sel->this);
+		put_entry(sel->this, entry, FALSE, TRUE);
+	}
+	return JOB_REQUEUE_NONE;
+}
+
+METHOD(vici_socket_t, send_, void,
+	private_vici_socket_t *this, u_int id, chunk_t msg)
+{
+	if (msg.len <= VICI_MESSAGE_SIZE_MAX)
+	{
+		entry_selector_t *sel;
+		msg_buf_t *out;
+		entry_t *entry;
+
+		entry = find_entry(this, NULL, id, FALSE, TRUE);
+		if (entry)
+		{
+			INIT(out,
+				.buf = msg,
+			);
+			htoun32(out->hdr, msg.len);
+
+			array_insert(entry->out, ARRAY_TAIL, out);
+			if (array_count(entry->out) == 1)
+			{	/* asynchronously re-enable on_write callback when we get data */
+				INIT(sel,
+					.this = this,
+					.id = entry->id,
+				);
+				lib->processor->queue_job(lib->processor,
+							(job_t*)callback_job_create(enable_writer,
+														sel, free, NULL));
+			}
+			put_entry(this, entry, FALSE, TRUE);
+		}
+		else
+		{
+			DBG1(DBG_CFG, "vici connection %u unknown", id);
+			chunk_clear(&msg);
+		}
+	}
+	else
+	{
+		DBG1(DBG_CFG, "vici message size %zu exceeds maximum size of %u, "
+			 "discarded", msg.len, VICI_MESSAGE_SIZE_MAX);
+		chunk_clear(&msg);
+	}
+}
+
+METHOD(vici_socket_t, destroy, void,
+	private_vici_socket_t *this)
+{
+	DESTROY_IF(this->service);
+	this->connections->destroy_function(this->connections, destroy_entry);
+	this->mutex->destroy(this->mutex);
+	free(this);
+}
+
+/*
+ * see header file
+ */
+vici_socket_t *vici_socket_create(char *uri, vici_inbound_cb_t inbound,
+								  vici_connect_cb_t connect,
+								  vici_disconnect_cb_t disconnect, void *user)
+{
+	private_vici_socket_t *this;
+
+	INIT(this,
+		.public = {
+			.send = _send_,
+			.destroy = _destroy,
+		},
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+		.connections = linked_list_create(),
+		.inbound = inbound,
+		.connect = connect,
+		.disconnect = disconnect,
+		.user = user,
+	);
+
+	this->service = lib->streams->create_service(lib->streams, uri, 3);
+	if (!this->service)
+	{
+		DBG1(DBG_CFG, "creating vici socket failed");
+		destroy(this);
+		return NULL;
+	}
+	this->service->on_accept(this->service, on_accept, this,
+							 JOB_PRIO_CRITICAL, 0);
+
+	return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_socket.h b/src/libcharon/plugins/vici/vici_socket.h
new file mode 100644
index 0000000..8727836
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_socket.h
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup vici_socket vici_socket
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_SOCKET_H_
+#define VICI_SOCKET_H_
+
+#include <library.h>
+
+/**
+ * Maximum size of a single message exchanged.
+ */
+#define VICI_MESSAGE_SIZE_MAX (512 * 1024)
+
+typedef struct vici_socket_t vici_socket_t;
+
+/**
+ * Callback function for dispatching inbound client messages.
+ *
+ * @param user		user data, as passed during registration
+ * @param id		unique client connection identifier
+ * @param data		incoming message data
+ */
+typedef void (*vici_inbound_cb_t)(void *user, u_int id, chunk_t data);
+
+/**
+ * Callback function invoked when new clients connect
+ *
+ * @param user		user data, as passed during registration
+ * @param id		unique client connection identifier
+ * @return			client connection context
+ */
+typedef void (*vici_connect_cb_t)(void *user, u_int id);
+
+/**
+ * Callback function invoked when connected clients disconnect
+ *
+ * @param user		user data, as passed during registration
+ * @param id		unique client connection identifier
+ */
+typedef void (*vici_disconnect_cb_t)(void *user, u_int id);
+
+/**
+ * Vici socket, low level socket input/output handling.
+ *
+ * On the socket, we pass raw chunks having a 2 byte network order length
+ * prefix. The length field does not count the length header itself, and
+ * is not included in the data passed over this interface.
+ */
+struct vici_socket_t {
+
+	/**
+	 * Send a message to a client identified by connection identifier.
+	 *
+	 * @param id		unique client connection identifier
+	 * @param data		data to send to client, gets owned
+	 */
+	void (*send)(vici_socket_t *this, u_int id, chunk_t data);
+
+	/**
+	 * Destroy socket.
+	 */
+	void (*destroy)(vici_socket_t *this);
+};
+
+/**
+ * Create a vici_socket instance.
+ *
+ * @param uri			socket URI to listen on
+ * @param inbound		inbound message callback
+ * @param connect		connect callback
+ * @param disconnect	disconnect callback
+ * @param user			user data to pass to callbacks
+ */
+vici_socket_t *vici_socket_create(char *uri, vici_inbound_cb_t inbound,
+								  vici_connect_cb_t connect,
+								  vici_disconnect_cb_t disconnect, void *user);
+
+#endif /** VICI_SOCKET_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_tests.c b/src/libcharon/plugins/vici/vici_tests.c
new file mode 100644
index 0000000..434aa5e
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_tests.c
@@ -0,0 +1,46 @@
+/*
+ * 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 <daemon.h>
+#include <hydra.h>
+
+/* declare test suite constructors */
+#define TEST_SUITE(x) test_suite_t* x();
+#include "vici_tests.h"
+#undef TEST_SUITE
+
+static test_configuration_t tests[] = {
+#define TEST_SUITE(x) \
+	{ .suite = x, },
+#include "vici_tests.h"
+	{ .suite = NULL, }
+};
+
+static bool test_runner_init(bool init)
+{
+	if (!init)
+	{
+		lib->processor->set_threads(lib->processor, 0);
+		lib->processor->cancel(lib->processor);
+	}
+	return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+	return test_runner_run("vici", tests, test_runner_init);
+}
diff --git a/src/libcharon/plugins/vici/vici_tests.h b/src/libcharon/plugins/vici/vici_tests.h
new file mode 100644
index 0000000..3e8f170
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_tests.h
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+TEST_SUITE(socket_suite_create)
+TEST_SUITE(message_suite_create)
+TEST_SUITE(request_suite_create)
+TEST_SUITE(event_suite_create)
diff --git a/src/libcharon/plugins/whitelist/Makefile.am b/src/libcharon/plugins/whitelist/Makefile.am
index e02b4a0..1fd01c8 100644
--- a/src/libcharon/plugins/whitelist/Makefile.am
+++ b/src/libcharon/plugins/whitelist/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-whitelist.la
diff --git a/src/libcharon/plugins/whitelist/Makefile.in b/src/libcharon/plugins/whitelist/Makefile.in
index e3588ad..8a714a9 100644
--- a/src/libcharon/plugins/whitelist/Makefile.in
+++ b/src/libcharon/plugins/whitelist/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -273,6 +273,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -291,6 +292,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -318,6 +320,7 @@ 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@
@@ -409,6 +412,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -426,7 +430,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_PIDDIR=\"${piddir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-whitelist.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-whitelist.la
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.am b/src/libcharon/plugins/xauth_eap/Makefile.am
index 21f8d02..ea75c15 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.am
+++ b/src/libcharon/plugins/xauth_eap/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-xauth-eap.la
diff --git a/src/libcharon/plugins/xauth_eap/Makefile.in b/src/libcharon/plugins/xauth_eap/Makefile.in
index b78a917..26bb6fb 100644
--- a/src/libcharon/plugins/xauth_eap/Makefile.in
+++ b/src/libcharon/plugins/xauth_eap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-xauth-eap.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-xauth-eap.la
diff --git a/src/libcharon/plugins/xauth_eap/xauth_eap.c b/src/libcharon/plugins/xauth_eap/xauth_eap.c
index f597bb7..f21d026 100644
--- a/src/libcharon/plugins/xauth_eap/xauth_eap.c
+++ b/src/libcharon/plugins/xauth_eap/xauth_eap.c
@@ -163,11 +163,11 @@ METHOD(xauth_method_t, initiate, status_t,
 {
 	cp_payload_t *cp;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-				CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+				PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-				CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+				PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
 	*out = cp;
 	return NEED_MORE;
 }
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.am b/src/libcharon/plugins/xauth_generic/Makefile.am
index d48e52d..1ecd9fd 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.am
+++ b/src/libcharon/plugins/xauth_generic/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-xauth-generic.la
diff --git a/src/libcharon/plugins/xauth_generic/Makefile.in b/src/libcharon/plugins/xauth_generic/Makefile.in
index e4d96a9..f06fdb5 100644
--- a/src/libcharon/plugins/xauth_generic/Makefile.in
+++ b/src/libcharon/plugins/xauth_generic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-xauth-generic.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-xauth-generic.la
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic.c b/src/libcharon/plugins/xauth_generic/xauth_generic.c
index 5df8aad..c37da0c 100644
--- a/src/libcharon/plugins/xauth_generic/xauth_generic.c
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic.c
@@ -69,7 +69,7 @@ METHOD(xauth_method_t, process_peer, status_t,
 	}
 	enumerator->destroy(enumerator);
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
 
 	enumerator = in->create_attribute_enumerator(in);
 	while (enumerator->enumerate(enumerator, &attr))
@@ -80,7 +80,7 @@ METHOD(xauth_method_t, process_peer, status_t,
 		{
 			case XAUTH_USER_NAME:
 				cp->add_attribute(cp, configuration_attribute_create_chunk(
-							CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME,
+							PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME,
 							this->peer->get_encoding(this->peer)));
 				break;
 			case XAUTH_NEXT_PIN:
@@ -99,7 +99,7 @@ METHOD(xauth_method_t, process_peer, status_t,
 					return FAILED;
 				}
 				cp->add_attribute(cp, configuration_attribute_create_chunk(
-							CONFIGURATION_ATTRIBUTE_V1, attr->get_type(attr),
+							PLV1_CONFIGURATION_ATTRIBUTE, attr->get_type(attr),
 							shared->get_key(shared)));
 				shared->destroy(shared);
 				break;
@@ -118,11 +118,11 @@ METHOD(xauth_method_t, initiate_server, status_t,
 {
 	cp_payload_t *cp;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-				CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+				PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-				CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+				PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
 	*out = cp;
 	return NEED_MORE;
 }
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.am b/src/libcharon/plugins/xauth_noauth/Makefile.am
index f1581ba..3902471 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.am
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-xauth-noauth.la
diff --git a/src/libcharon/plugins/xauth_noauth/Makefile.in b/src/libcharon/plugins/xauth_noauth/Makefile.in
index 5fe4c06..72f3dc6 100644
--- a/src/libcharon/plugins/xauth_noauth/Makefile.in
+++ b/src/libcharon/plugins/xauth_noauth/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-xauth-noauth.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-xauth-noauth.la
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.am b/src/libcharon/plugins/xauth_pam/Makefile.am
index 1875f81..abf83ca 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.am
+++ b/src/libcharon/plugins/xauth_pam/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-xauth-pam.la
diff --git a/src/libcharon/plugins/xauth_pam/Makefile.in b/src/libcharon/plugins/xauth_pam/Makefile.in
index 2a6aec0..9af015e 100644
--- a/src/libcharon/plugins/xauth_pam/Makefile.in
+++ b/src/libcharon/plugins/xauth_pam/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libcharon
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-xauth-pam.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-xauth-pam.la
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam.c b/src/libcharon/plugins/xauth_pam/xauth_pam.c
index 71c79ec..3414d2e 100644
--- a/src/libcharon/plugins/xauth_pam/xauth_pam.c
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam.c
@@ -43,11 +43,11 @@ METHOD(xauth_method_t, initiate, status_t,
 {
 	cp_payload_t *cp;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-				CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
+				PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
 	cp->add_attribute(cp, configuration_attribute_create_chunk(
-				CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
+				PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
 	*out = cp;
 	return NEED_MORE;
 }
@@ -153,7 +153,12 @@ METHOD(xauth_method_t, process, status_t,
 				attr2string(user, sizeof(user), chunk);
 				break;
 			case XAUTH_USER_PASSWORD:
-				attr2string(pass, sizeof(pass), attr->get_chunk(attr));
+				chunk = attr->get_chunk(attr);
+				if (chunk.len && chunk.ptr[chunk.len - 1] == 0)
+				{	/* fix null-terminated passwords (Android etc.) */
+					chunk.len -= 1;
+				}
+				attr2string(pass, sizeof(pass), chunk);
 				break;
 			default:
 				break;
diff --git a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
index 5b15410..fd11223 100644
--- a/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
+++ b/src/libcharon/plugins/xauth_pam/xauth_pam_listener.h
@@ -26,7 +26,7 @@
  * @{ @ingroup xauth_pam
  */
 
-#ifndef XAUTH_PAM_LISENER_H_
+#ifndef XAUTH_PAM_LISTENER_H_
 #define XAUTH_PAM_LISTENER_H_
 
 typedef struct xauth_pam_listener_t xauth_pam_listener_t;
diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c
index 606135b..a6795e7 100644
--- a/src/libcharon/processing/jobs/process_message_job.c
+++ b/src/libcharon/processing/jobs/process_message_job.c
@@ -51,7 +51,7 @@ METHOD(job_t, execute, job_requeue_t,
 	/* if this is an unencrypted INFORMATIONAL exchange it is likely a
 	 * connectivity check. */
 	if (this->message->get_exchange_type(this->message) == INFORMATIONAL &&
-		this->message->get_first_payload_type(this->message) != ENCRYPTED)
+		this->message->get_first_payload_type(this->message) != PLV2_ENCRYPTED)
 	{
 		/* theoretically this could also be an error message
 		 * see RFC 4306, section 1.5. */
diff --git a/src/libcharon/processing/jobs/rekey_ike_sa_job.c b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
index 712c7c2..516dc5d 100644
--- a/src/libcharon/processing/jobs/rekey_ike_sa_job.c
+++ b/src/libcharon/processing/jobs/rekey_ike_sa_job.c
@@ -46,11 +46,47 @@ METHOD(job_t, destroy, void,
 	free(this);
 }
 
+/**
+ * Check if we should delay a reauth, and by how many seconds
+ */
+static u_int32_t get_retry_delay(ike_sa_t *ike_sa)
+{
+	enumerator_t *enumerator;
+	child_sa_t *child_sa;
+	u_int32_t retry = 0;
+
+	/* avoid reauth collisions for certain IKE_SA/CHILD_SA states */
+	if (ike_sa->get_state(ike_sa) != IKE_ESTABLISHED)
+	{
+		retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+		DBG1(DBG_IKE, "unable to reauthenticate in %N state, delaying for %us",
+			 ike_sa_state_names, ike_sa->get_state(ike_sa), retry);
+	}
+	else
+	{
+		enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+		while (enumerator->enumerate(enumerator, &child_sa))
+		{
+			if (child_sa->get_state(child_sa) != CHILD_INSTALLED)
+			{
+				retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
+				DBG1(DBG_IKE, "unable to reauthenticate in CHILD_SA %N state, "
+					 "delaying for %us", child_sa_state_names,
+					 child_sa->get_state(child_sa), retry);
+				break;
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+	return retry;
+}
+
 METHOD(job_t, execute, job_requeue_t,
 	private_rekey_ike_sa_job_t *this)
 {
 	ike_sa_t *ike_sa;
 	status_t status = SUCCESS;
+	u_int32_t retry = 0;
 
 	ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
 											  this->ike_sa_id);
@@ -62,7 +98,11 @@ METHOD(job_t, execute, job_requeue_t,
 	{
 		if (this->reauth)
 		{
-			status = ike_sa->reauth(ike_sa);
+			retry = get_retry_delay(ike_sa);
+			if (!retry)
+			{
+				status = ike_sa->reauth(ike_sa);
+			}
 		}
 		else
 		{
@@ -71,13 +111,18 @@ METHOD(job_t, execute, job_requeue_t,
 
 		if (status == DESTROY_ME)
 		{
-			charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+			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);
 		}
 	}
+	if (retry)
+	{
+		return JOB_RESCHEDULE(retry);
+	}
 	return JOB_REQUEUE_NONE;
 }
 
diff --git a/src/libcharon/sa/authenticator.c b/src/libcharon/sa/authenticator.c
index a32b6ab..8571274 100644
--- a/src/libcharon/sa/authenticator.c
+++ b/src/libcharon/sa/authenticator.c
@@ -86,7 +86,7 @@ authenticator_t *authenticator_create_verifier(
 {
 	auth_payload_t *auth_payload;
 
-	auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+	auth_payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
 	if (auth_payload == NULL)
 	{
 		return (authenticator_t*)eap_authenticator_create_verifier(ike_sa,
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 720a585..a96ab4e 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -722,8 +722,8 @@ METHOD(child_sa_t, install, status_t,
 				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,
-				this->ipcomp, cpi, initiator, this->encap, esn, update,
-				src_ts, dst_ts);
+				this->ipcomp, cpi, this->config->get_replay_window(this->config),
+				initiator, this->encap, esn, update, src_ts, dst_ts);
 
 	free(lifetime);
 
@@ -731,6 +731,17 @@ METHOD(child_sa_t, install, status_t,
 }
 
 /**
+ * Check kernel interface if policy updates are required
+ */
+static bool require_policy_update()
+{
+	kernel_feature_t f;
+
+	f = hydra->kernel_interface->get_features(hydra->kernel_interface);
+	return !(f & KERNEL_NO_POLICY_UPDATES);
+}
+
+/**
  * Install 3 policies: out, in and forward
  */
 static status_t install_policies_internal(private_child_sa_t *this,
@@ -836,13 +847,21 @@ METHOD(child_sa_t, add_policies, status_t,
 		priority = this->trap ? POLICY_PRIORITY_ROUTED
 							  : POLICY_PRIORITY_DEFAULT;
 
+		enumerator = create_policy_enumerator(this);
+		while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+		{
+			my_sa.policy_count++;
+			other_sa.policy_count++;
+		}
+		enumerator->destroy(enumerator);
+
 		/* enumerate pairs of traffic selectors */
 		enumerator = create_policy_enumerator(this);
 		while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
 		{
 			/* install outbound drop policy to avoid packets leaving unencrypted
 			 * when updating policies */
-			if (priority == POLICY_PRIORITY_DEFAULT)
+			if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update())
 			{
 				status |= install_policies_internal(this, this->my_addr,
 									this->other_addr, my_ts, other_ts,
@@ -916,6 +935,7 @@ METHOD(child_sa_t, update, status_t,
 							this->other_addr, this->my_addr, other, me,
 							this->encap, encap, this->mark_in) == NOT_SUPPORTED)
 			{
+				set_state(this, old);
 				return NOT_SUPPORTED;
 			}
 		}
@@ -929,12 +949,13 @@ METHOD(child_sa_t, update, status_t,
 							this->my_addr, this->other_addr, me, other,
 							this->encap, encap, this->mark_out) == NOT_SUPPORTED)
 			{
+				set_state(this, old);
 				return NOT_SUPPORTED;
 			}
 		}
 	}
 
-	if (this->config->install_policy(this->config))
+	if (this->config->install_policy(this->config) && require_policy_update())
 	{
 		ipsec_sa_cfg_t my_sa = {
 			.mode = this->mode,
@@ -1073,7 +1094,7 @@ METHOD(child_sa_t, destroy, void,
 		while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
 		{
 			del_policies_internal(this, my_ts, other_ts, priority);
-			if (priority == POLICY_PRIORITY_DEFAULT)
+			if (priority == POLICY_PRIORITY_DEFAULT && require_policy_update())
 			{
 				del_policies_internal(this, my_ts, other_ts,
 									  POLICY_PRIORITY_FALLBACK);
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 2c15dc5..c338cda 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -2001,6 +2001,26 @@ METHOD(ike_sa_t, add_configuration_attribute, void,
 	array_insert(this->attributes, ARRAY_TAIL, &entry);
 }
 
+/**
+ * Enumerator filter for attributes
+ */
+static bool filter_attribute(void *null, attribute_entry_t **in,
+							 configuration_attribute_type_t *type, void *in2,
+							 chunk_t *data, void *in3, bool *handled)
+{
+	*type = (*in)->type;
+	*data = (*in)->data;
+	*handled = (*in)->handler != NULL;
+	return TRUE;
+}
+
+METHOD(ike_sa_t, create_attribute_enumerator, enumerator_t*,
+	private_ike_sa_t *this)
+{
+	return enumerator_create_filter(array_create_enumerator(this->attributes),
+									(void*)filter_attribute, NULL, NULL);
+}
+
 METHOD(ike_sa_t, create_task_enumerator, enumerator_t*,
 	private_ike_sa_t *this, task_queue_t queue)
 {
@@ -2019,7 +2039,24 @@ METHOD(ike_sa_t, queue_task, void,
 	this->task_manager->queue_task(this->task_manager, task);
 }
 
-METHOD(ike_sa_t, inherit, void,
+METHOD(ike_sa_t, inherit_pre, void,
+	private_ike_sa_t *this, ike_sa_t *other_public)
+{
+	private_ike_sa_t *other = (private_ike_sa_t*)other_public;
+
+	/* apply config and hosts */
+	set_peer_cfg(this, other->peer_cfg);
+	set_my_host(this, other->my_host->clone(other->my_host));
+	set_other_host(this, other->other_host->clone(other->other_host));
+
+	/* apply extensions and conditions with a few exceptions */
+	this->extensions = other->extensions;
+	this->conditions = other->conditions;
+	this->conditions &= ~COND_STALE;
+	this->conditions &= ~COND_REAUTHENTICATING;
+}
+
+METHOD(ike_sa_t, inherit_post, void,
 	private_ike_sa_t *this, ike_sa_t *other_public)
 {
 	private_ike_sa_t *other = (private_ike_sa_t*)other_public;
@@ -2131,10 +2168,14 @@ METHOD(ike_sa_t, destroy, void,
 	}
 
 	/* remove attributes first, as we pass the IKE_SA to the handler */
+	charon->bus->handle_vips(charon->bus, &this->public, FALSE);
 	while (array_remove(this->attributes, ARRAY_TAIL, &entry))
 	{
-		hydra->attributes->release(hydra->attributes, entry.handler,
-								   this->other_id, entry.type, entry.data);
+		if (entry.handler)
+		{
+			hydra->attributes->release(hydra->attributes, entry.handler,
+									   this->other_id, entry.type, entry.data);
+		}
 		free(entry.data.ptr);
 	}
 	/* uninstall CHILD_SAs before virtual IPs, otherwise we might kill
@@ -2288,7 +2329,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 			.reestablish = _reestablish,
 			.set_auth_lifetime = _set_auth_lifetime,
 			.roam = _roam,
-			.inherit = _inherit,
+			.inherit_pre = _inherit_pre,
+			.inherit_post = _inherit_post,
 			.generate_message = _generate_message,
 			.reset = _reset,
 			.get_unique_id = _get_unique_id,
@@ -2296,6 +2338,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
 			.clear_virtual_ips = _clear_virtual_ips,
 			.create_virtual_ip_enumerator = _create_virtual_ip_enumerator,
 			.add_configuration_attribute = _add_configuration_attribute,
+			.create_attribute_enumerator = _create_attribute_enumerator,
 			.set_kmaddress = _set_kmaddress,
 			.create_task_enumerator = _create_task_enumerator,
 			.flush_queue = _flush_queue,
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 00c16c0..15fb474 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -978,6 +978,9 @@ struct ike_sa_t {
 	 * registered at the IKE_SA. Attributes are inherit()ed and get released
 	 * when the IKE_SA is closed.
 	 *
+	 * Unhandled attributes are passed as well, but with a NULL handler. They
+	 * do not get released.
+	 *
 	 * @param handler		handler installed the attribute, use for release()
 	 * @param type			configuration attribute type
 	 * @param data			associated attribute data
@@ -987,6 +990,17 @@ struct ike_sa_t {
 							configuration_attribute_type_t type, chunk_t data);
 
 	/**
+	 * Create an enumerator over received configuration attributes.
+	 *
+	 * The resulting enumerator is over the configuration_attribute_type_t type,
+	 * a value chunk_t followed by a bool flag. The boolean flag indicates if
+	 * the attribute has been handled by an attribute handler.
+	 *
+	 * @return				enumerator over type, value and the "handled" flag.
+	 */
+	enumerator_t* (*create_attribute_enumerator)(ike_sa_t *this);
+
+	/**
 	 * Set local and remote host addresses to be used for IKE.
 	 *
 	 * These addresses are communicated via the KMADDRESS field of a MIGRATE
@@ -1020,6 +1034,16 @@ struct ike_sa_t {
 	void (*queue_task)(ike_sa_t *this, task_t *task);
 
 	/**
+	 * Inherit required attributes to new SA before rekeying.
+	 *
+	 * Some properties of the SA must be applied before starting IKE_SA
+	 * rekeying, such as the configuration or support extensions.
+	 *
+	 * @param other			other IKE_SA to inherit from
+	 */
+	void (*inherit_pre)(ike_sa_t *this, ike_sa_t *other);
+
+	/**
 	 * Inherit all attributes of other to this after rekeying.
 	 *
 	 * When rekeying is completed, all CHILD_SAs, the virtual IP and all
@@ -1027,7 +1051,7 @@ struct ike_sa_t {
 	 *
 	 * @param other			other IKE SA to inherit from
 	 */
-	void (*inherit) (ike_sa_t *this, ike_sa_t *other);
+	void (*inherit_post) (ike_sa_t *this, ike_sa_t *other);
 
 	/**
 	 * Reset the IKE_SA, useable when initiating fails
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index f2f81cf..8e68e7b 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -354,6 +354,11 @@ struct private_ike_sa_manager_t {
 	shareable_segment_t *half_open_segments;
 
 	/**
+	 * Total number of half-open IKE_SAs.
+	 */
+	refcount_t half_open_count;
+
+	/**
 	 * Hash table with connected_peers_t objects.
 	 */
 	table_item_t **connected_peers_table;
@@ -764,6 +769,7 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
 		this->half_open_table[row] = item;
 	}
 	this->half_open_segments[segment].count++;
+	ref_get(&this->half_open_count);
 	lock->unlock(lock);
 }
 
@@ -803,6 +809,7 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
 				free(item);
 			}
 			this->half_open_segments[segment].count--;
+			ignore_result(ref_put(&this->half_open_count));
 			break;
 		}
 		prev = item;
@@ -964,7 +971,7 @@ static bool get_init_hash(private_ike_sa_manager_t *this, message_t *message,
 	{	/* this might be the case when flush() has been called */
 		return FALSE;
 	}
-	if (message->get_first_payload_type(message) == FRAGMENT_V1)
+	if (message->get_first_payload_type(message) == PLV1_FRAGMENT)
 	{	/* only hash the source IP, port and SPI for fragmented init messages */
 		u_int16_t port;
 		u_int64_t spi;
@@ -1306,7 +1313,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 
 			ike_id = entry->ike_sa->get_id(entry->ike_sa);
 			entry->checked_out = TRUE;
-			if (message->get_first_payload_type(message) != FRAGMENT_V1)
+			if (message->get_first_payload_type(message) != PLV1_FRAGMENT)
 			{
 				entry->processing = get_message_id_or_hash(message);
 			}
@@ -1962,13 +1969,7 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
 	}
 	else
 	{
-		for (segment = 0; segment < this->segment_count; segment++)
-		{
-			lock = this->half_open_segments[segment].lock;
-			lock->read_lock(lock);
-			count += this->half_open_segments[segment].count;
-			lock->unlock(lock);
-		}
+		count = (u_int)ref_cur(&this->half_open_count);
 	}
 	return count;
 }
diff --git a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
index ee15408..aa966cd 100644
--- a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
+++ b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
@@ -85,7 +85,7 @@ METHOD(authenticator_t, build, status_t,
 	}
 	free(dh.ptr);
 
-	hash_payload = hash_payload_create(HASH_V1);
+	hash_payload = hash_payload_create(PLV1_HASH);
 	hash_payload->set_hash(hash_payload, hash);
 	message->add_payload(message, &hash_payload->payload_interface);
 	free(hash.ptr);
@@ -101,7 +101,7 @@ METHOD(authenticator_t, process, status_t,
 	chunk_t hash, dh;
 	auth_cfg_t *auth;
 
-	hash_payload = (hash_payload_t*)message->get_payload(message, HASH_V1);
+	hash_payload = (hash_payload_t*)message->get_payload(message, PLV1_HASH);
 	if (!hash_payload)
 	{
 		DBG1(DBG_IKE, "HASH payload missing in message");
diff --git a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
index d81c77f..bfe5ff4 100644
--- a/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
+++ b/src/libcharon/sa/ikev1/authenticators/pubkey_v1_authenticator.c
@@ -108,7 +108,7 @@ METHOD(authenticator_t, build, status_t,
 
 	if (private->sign(private, scheme, hash, &sig))
 	{
-		sig_payload = hash_payload_create(SIGNATURE_V1);
+		sig_payload = hash_payload_create(PLV1_SIGNATURE);
 		sig_payload->set_hash(sig_payload, sig);
 		free(sig.ptr);
 		message->add_payload(message, &sig_payload->payload_interface);
@@ -144,7 +144,7 @@ METHOD(authenticator_t, process, status_t,
 		scheme = SIGN_ECDSA_WITH_NULL;
 	}
 
-	sig_payload = (hash_payload_t*)message->get_payload(message, SIGNATURE_V1);
+	sig_payload = (hash_payload_t*)message->get_payload(message, PLV1_SIGNATURE);
 	if (!sig_payload)
 	{
 		DBG1(DBG_IKE, "SIG payload missing in message");
diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c
index bf1b004..619d197 100644
--- a/src/libcharon/sa/ikev1/keymat_v1.c
+++ b/src/libcharon/sa/ikev1/keymat_v1.c
@@ -791,7 +791,7 @@ METHOD(keymat_v1_t, get_hash, bool,
 static bool get_nonce(message_t *message, chunk_t *n)
 {
 	nonce_payload_t *nonce;
-	nonce = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
+	nonce = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
 	if (nonce)
 	{
 		*n = nonce->get_nonce(nonce);
@@ -815,7 +815,7 @@ static chunk_t get_message_data(message_t *message, generator_t *generator)
 		enumerator = message->create_payload_enumerator(message);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			if (payload->get_type(payload) == HASH_V1)
+			if (payload->get_type(payload) == PLV1_HASH)
 			{
 				continue;
 			}
@@ -835,7 +835,7 @@ static chunk_t get_message_data(message_t *message, generator_t *generator)
 				generator->generate_payload(generator, payload);
 				payload = next;
 			}
-			payload->set_next_type(payload, NO_PAYLOAD);
+			payload->set_next_type(payload, PL_NONE);
 			generator->generate_payload(generator, payload);
 		}
 		enumerator->destroy(enumerator);
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c
index 1189d3c..114b8a3 100644
--- a/src/libcharon/sa/ikev1/phase1.c
+++ b/src/libcharon/sa/ikev1/phase1.c
@@ -648,7 +648,7 @@ METHOD(phase1_t, save_sa_payload, bool,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
+		if (payload->get_type(payload) == PLV1_SECURITY_ASSOCIATION)
 		{
 			sa = payload;
 			break;
@@ -682,7 +682,7 @@ METHOD(phase1_t, add_nonce_ke, bool,
 	nonce_gen_t *nonceg;
 	chunk_t nonce;
 
-	ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
+	ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, this->dh);
 	message->add_payload(message, &ke_payload->payload_interface);
 
 	nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
@@ -699,7 +699,7 @@ METHOD(phase1_t, add_nonce_ke, bool,
 	}
 	nonceg->destroy(nonceg);
 
-	nonce_payload = nonce_payload_create(NONCE_V1);
+	nonce_payload = nonce_payload_create(PLV1_NONCE);
 	nonce_payload->set_nonce(nonce_payload, nonce);
 	message->add_payload(message, &nonce_payload->payload_interface);
 
@@ -720,7 +720,7 @@ METHOD(phase1_t, get_nonce_ke, bool,
 	nonce_payload_t *nonce_payload;
 	ke_payload_t *ke_payload;
 
-	ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
+	ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
 	if (!ke_payload)
 	{
 		DBG1(DBG_IKE, "KE payload missing in message");
@@ -729,7 +729,7 @@ METHOD(phase1_t, get_nonce_ke, bool,
 	this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
 	this->dh->set_other_public_value(this->dh, this->dh_value);
 
-	nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
+	nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
 	if (!nonce_payload)
 	{
 		DBG1(DBG_IKE, "NONCE payload missing in message");
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 8fc158b..97812a5 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -956,7 +956,7 @@ static void send_notify(private_task_manager_t *this, message_t *request,
 	response->set_request(response, TRUE);
 	response->set_message_id(response, mid);
 	response->add_payload(response, (payload_t*)
-				notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+				notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
 													PROTO_IKE, type));
 
 	me = this->ike_sa->get_my_host(this->ike_sa);
@@ -1265,7 +1265,7 @@ static status_t handle_fragment(private_task_manager_t *this, message_t *msg)
 	chunk_t data;
 	u_int8_t num;
 
-	payload = (fragment_payload_t*)msg->get_payload(msg, FRAGMENT_V1);
+	payload = (fragment_payload_t*)msg->get_payload(msg, PLV1_FRAGMENT);
 	if (!payload)
 	{
 		return FAILED;
@@ -1412,7 +1412,7 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg)
 		}
 	}
 
-	if (msg->get_first_payload_type(msg) == FRAGMENT_V1)
+	if (msg->get_first_payload_type(msg) == PLV1_FRAGMENT)
 	{
 		return handle_fragment(this, msg);
 	}
@@ -1514,7 +1514,7 @@ METHOD(task_manager_t, process_message, status_t,
 		{
 			if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED &&
 				this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING &&
-				msg->get_first_payload_type(msg) != FRAGMENT_V1)
+				msg->get_first_payload_type(msg) != PLV1_FRAGMENT)
 			{
 				DBG1(DBG_IKE, "ignoring %N in established IKE_SA state",
 					 exchange_type_names, msg->get_exchange_type(msg));
diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
index 6cc3e04..7009ae9 100644
--- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c
@@ -133,7 +133,7 @@ static bool has_notify_errors(private_aggressive_mode_t *this, message_t *messag
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY_V1)
+		if (payload->get_type(payload) == PLV1_NOTIFY)
 		{
 			notify_payload_t *notify;
 			notify_type_t type;
@@ -167,7 +167,7 @@ static status_t send_notify(private_aggressive_mode_t *this, notify_type_t type)
 	u_int64_t spi_i, spi_r;
 	chunk_t spi;
 
-	notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+	notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
 														  PROTO_IKE, type);
 	ike_sa_id = this->ike_sa->get_id(this->ike_sa);
 	spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
@@ -276,7 +276,7 @@ METHOD(task_t, build_i, status_t,
 				return FAILED;
 			}
 			this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
-			id_payload = id_payload_create_from_identification(ID_V1, id);
+			id_payload = id_payload_create_from_identification(PLV1_ID, id);
 			this->id_data = id_payload->get_encoded(id_payload);
 			message->add_payload(message, &id_payload->payload_interface);
 
@@ -389,7 +389,7 @@ METHOD(task_t, process_r, status_t,
 									   message->get_source(message), TRUE);
 
 			sa_payload = (sa_payload_t*)message->get_payload(message,
-													SECURITY_ASSOCIATION_V1);
+													PLV1_SECURITY_ASSOCIATION);
 			if (!sa_payload)
 			{
 				DBG1(DBG_IKE, "SA payload missing");
@@ -448,7 +448,7 @@ METHOD(task_t, process_r, status_t,
 				return send_notify(this, INVALID_PAYLOAD_TYPE);
 			}
 
-			id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+			id_payload = (id_payload_t*)message->get_payload(message, PLV1_ID);
 			if (!id_payload)
 			{
 				DBG1(DBG_IKE, "IDii payload missing");
@@ -588,7 +588,7 @@ METHOD(task_t, build_r, status_t,
 		}
 		this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
 
-		id_payload = id_payload_create_from_identification(ID_V1, id);
+		id_payload = id_payload_create_from_identification(PLV1_ID, id);
 		message->add_payload(message, &id_payload->payload_interface);
 
 		if (!this->ph1->build_auth(this->ph1, this->method, message,
@@ -614,7 +614,7 @@ METHOD(task_t, process_i, status_t,
 		u_int32_t lifetime;
 
 		sa_payload = (sa_payload_t*)message->get_payload(message,
-												SECURITY_ASSOCIATION_V1);
+												PLV1_SECURITY_ASSOCIATION);
 		if (!sa_payload)
 		{
 			DBG1(DBG_IKE, "SA payload missing");
@@ -654,7 +654,7 @@ METHOD(task_t, process_i, status_t,
 			return send_notify(this, NO_PROPOSAL_CHOSEN);
 		}
 
-		id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+		id_payload = (id_payload_t*)message->get_payload(message, PLV1_ID);
 		if (!id_payload)
 		{
 			DBG1(DBG_IKE, "IDir payload missing");
diff --git a/src/libcharon/sa/ikev1/tasks/informational.c b/src/libcharon/sa/ikev1/tasks/informational.c
index bda1d2a..b742dbe 100644
--- a/src/libcharon/sa/ikev1/tasks/informational.c
+++ b/src/libcharon/sa/ikev1/tasks/informational.c
@@ -93,7 +93,7 @@ METHOD(task_t, process_r, status_t,
 	{
 		switch (payload->get_type(payload))
 		{
-			case NOTIFY_V1:
+			case PLV1_NOTIFY:
 				notify = (notify_payload_t*)payload;
 				type = notify->get_notify_type(notify);
 
@@ -153,7 +153,7 @@ METHOD(task_t, process_r, status_t,
 						 notify_type_names, type);
 				}
 				continue;
-			case DELETE_V1:
+			case PLV1_DELETE:
 				if (!this->del)
 				{
 					delete = (delete_payload_t*)payload;
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c b/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c
index edad3b2..7dbbdc9 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_cert_post.c
@@ -68,7 +68,7 @@ static bool use_certs(private_isakmp_cert_post_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
+		if (payload->get_type(payload) == PLV1_SECURITY_ASSOCIATION)
 		{
 			sa_payload_t *sa_payload = (sa_payload_t*)payload;
 
@@ -132,7 +132,7 @@ static void build_certs(private_isakmp_cert_post_t *this, message_t *message)
 			{
 				break;
 			}
-			payload = cert_payload_create_from_cert(CERTIFICATE_V1, cert);
+			payload = cert_payload_create_from_cert(PLV1_CERTIFICATE, cert);
 			if (!payload)
 			{
 				break;
@@ -146,7 +146,7 @@ static void build_certs(private_isakmp_cert_post_t *this, message_t *message)
 			{
 				if (type == AUTH_RULE_IM_CERT)
 				{
-					payload = cert_payload_create_from_cert(CERTIFICATE_V1, cert);
+					payload = cert_payload_create_from_cert(PLV1_CERTIFICATE, cert);
 					if (payload)
 					{
 						DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c b/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c
index 43a0aaa..58f856e 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_cert_pre.c
@@ -134,7 +134,7 @@ static void process_certreqs(private_isakmp_cert_pre_t *this, message_t *message
 	{
 		switch (payload->get_type(payload))
 		{
-			case CERTIFICATE_REQUEST_V1:
+			case PLV1_CERTREQ:
 			{
 				certificate_t *cert;
 
@@ -268,7 +268,7 @@ static void process_certs(private_isakmp_cert_pre_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == CERTIFICATE_V1)
+		if (payload->get_type(payload) == PLV1_CERTIFICATE)
 		{
 			cert_payload_t *cert_payload;
 			cert_encoding_t encoding;
@@ -377,7 +377,7 @@ static void build_certreqs(private_isakmp_cert_pre_t *this, message_t *message)
 		}
 		enumerator->destroy(enumerator);
 	}
-	if (!message->get_payload(message, CERTIFICATE_REQUEST_V1))
+	if (!message->get_payload(message, PLV1_CERTREQ))
 	{
 		/* otherwise add all trusted CA certificates */
 		enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
@@ -402,7 +402,7 @@ static bool use_certs(private_isakmp_cert_pre_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == SECURITY_ASSOCIATION_V1)
+		if (payload->get_type(payload) == PLV1_SECURITY_ASSOCIATION)
 		{
 			sa_payload_t *sa_payload = (sa_payload_t*)payload;
 
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_delete.c b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
index a44f3c4..bea0428 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_delete.c
@@ -50,7 +50,7 @@ METHOD(task_t, build_i, status_t,
 		 this->ike_sa->get_other_host(this->ike_sa),
 		 this->ike_sa->get_other_id(this->ike_sa));
 
-	delete_payload = delete_payload_create(DELETE_V1, PROTO_IKE);
+	delete_payload = delete_payload_create(PLV1_DELETE, PROTO_IKE);
 	id = this->ike_sa->get_id(this->ike_sa);
 	delete_payload->set_ike_spi(delete_payload, id->get_initiator_spi(id),
 								id->get_responder_spi(id));
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
index a3395a0..5522e92 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_dpd.c
@@ -55,7 +55,7 @@ METHOD(task_t, build, status_t,
 	u_int32_t seqnr;
 	chunk_t spi;
 
-	notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+	notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
 														  PROTO_IKE, this->type);
 	seqnr = htonl(this->seqnr);
 	ike_sa_id = this->ike_sa->get_id(this->ike_sa);
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
index fc6ac07..b8af6f6 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_natd.c
@@ -117,9 +117,9 @@ static payload_type_t get_nat_d_payload_type(ike_sa_t *ike_sa)
 {
 	if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
 	{
-		return NAT_D_DRAFT_00_03_V1;
+		return PLV1_NAT_D_DRAFT_00_03;
 	}
-	return NAT_D_V1;
+	return PLV1_NAT_D;
 }
 
 /**
@@ -269,8 +269,8 @@ static void process_payloads(private_isakmp_natd_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) != NAT_D_V1 &&
-			payload->get_type(payload) != NAT_D_DRAFT_00_03_V1)
+		if (payload->get_type(payload) != PLV1_NAT_D &&
+			payload->get_type(payload) != PLV1_NAT_D_DRAFT_00_03)
 		{
 			continue;
 		}
@@ -334,7 +334,7 @@ METHOD(task_t, build_i, status_t,
 		case ID_PROT:
 		{	/* add NAT-D payloads to the second request, need to process
 			 * those by the responder contained in the second response */
-			if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+			if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
 			{	/* wait for the second exchange */
 				return NEED_MORE;
 			}
@@ -362,7 +362,7 @@ METHOD(task_t, process_i, status_t,
 		case ID_PROT:
 		{	/* process NAT-D payloads in the second response, added them in the
 			 * second request already, so we're done afterwards */
-			if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+			if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
 			{	/* wait for the second exchange */
 				return NEED_MORE;
 			}
@@ -407,7 +407,7 @@ METHOD(task_t, process_r, status_t,
 		case ID_PROT:
 		{	/* process NAT-D payloads in the second request, need to add ours
 			 * to the second response */
-			if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+			if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
 			{	/* wait for the second exchange */
 				return NEED_MORE;
 			}
@@ -428,7 +428,7 @@ METHOD(task_t, build_r, status_t,
 		case ID_PROT:
 		{	/* add NAT-D payloads to second response, already processed those
 			 * contained in the second request */
-			if (message->get_payload(message, SECURITY_ASSOCIATION_V1))
+			if (message->get_payload(message, PLV1_SECURITY_ASSOCIATION))
 			{	/* wait for the second exchange */
 				return NEED_MORE;
 			}
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
index e07ac0a..426c4bd 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
@@ -209,7 +209,7 @@ static void build(private_isakmp_vendor_t *this, message_t *message)
 		   (vendor_ids[i].extension == EXT_IKE_FRAGMENTATION && fragmentation))
 		{
 			DBG2(DBG_IKE, "sending %s vendor ID", vendor_ids[i].desc);
-			vid_payload = vendor_id_payload_create_data(VENDOR_ID_V1,
+			vid_payload = vendor_id_payload_create_data(PLV1_VENDOR_ID,
 				chunk_clone(chunk_create(vendor_ids[i].id, vendor_ids[i].len)));
 			message->add_payload(message, &vid_payload->payload_interface);
 		}
@@ -220,7 +220,7 @@ static void build(private_isakmp_vendor_t *this, message_t *message)
 			this->best_natt_ext == i)
 		{
 			DBG2(DBG_IKE, "sending %s vendor ID", vendor_natt_ids[i].desc);
-			vid_payload = vendor_id_payload_create_data(VENDOR_ID_V1,
+			vid_payload = vendor_id_payload_create_data(PLV1_VENDOR_ID,
 							chunk_clone(chunk_create(vendor_natt_ids[i].id,
 													 vendor_natt_ids[i].len)));
 			message->add_payload(message, &vid_payload->payload_interface);
@@ -240,7 +240,7 @@ static void process(private_isakmp_vendor_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == VENDOR_ID_V1)
+		if (payload->get_type(payload) == PLV1_VENDOR_ID)
 		{
 			vendor_id_payload_t *vid;
 			bool found = FALSE;
diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c
index 8163816..8a5d9ae 100644
--- a/src/libcharon/sa/ikev1/tasks/main_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/main_mode.c
@@ -130,7 +130,7 @@ static bool has_notify_errors(private_main_mode_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY_V1)
+		if (payload->get_type(payload) == PLV1_NOTIFY)
 		{
 			notify_payload_t *notify;
 			notify_type_t type;
@@ -176,7 +176,7 @@ static status_t send_notify(private_main_mode_t *this, notify_type_t type)
 	u_int64_t spi_i, spi_r;
 	chunk_t spi;
 
-	notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+	notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
 														  PROTO_IKE, type);
 	ike_sa_id = this->ike_sa->get_id(this->ike_sa);
 	spi_i = ike_sa_id->get_initiator_spi(ike_sa_id);
@@ -302,7 +302,7 @@ METHOD(task_t, build_i, status_t,
 				return send_notify(this, INVALID_ID_INFORMATION);
 			}
 			this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
-			id_payload = id_payload_create_from_identification(ID_V1, id);
+			id_payload = id_payload_create_from_identification(PLV1_ID, id);
 			message->add_payload(message, &id_payload->payload_interface);
 
 			if (!this->ph1->build_auth(this->ph1, this->method, message,
@@ -340,7 +340,7 @@ METHOD(task_t, process_r, status_t,
 									   message->get_source(message), TRUE);
 
 			sa_payload = (sa_payload_t*)message->get_payload(message,
-													SECURITY_ASSOCIATION_V1);
+													PLV1_SECURITY_ASSOCIATION);
 			if (!sa_payload)
 			{
 				DBG1(DBG_IKE, "SA payload missing");
@@ -401,7 +401,7 @@ METHOD(task_t, process_r, status_t,
 			id_payload_t *id_payload;
 			identification_t *id;
 
-			id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+			id_payload = (id_payload_t*)message->get_payload(message, PLV1_ID);
 			if (!id_payload)
 			{
 				DBG1(DBG_IKE, "IDii payload missing");
@@ -488,7 +488,7 @@ METHOD(task_t, build_r, status_t,
 			}
 			this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
 
-			id_payload = id_payload_create_from_identification(ID_V1, id);
+			id_payload = id_payload_create_from_identification(PLV1_ID, id);
 			message->add_payload(message, &id_payload->payload_interface);
 
 			if (!this->ph1->build_auth(this->ph1, this->method, message,
@@ -575,7 +575,7 @@ METHOD(task_t, process_i, status_t,
 			bool private;
 
 			sa_payload = (sa_payload_t*)message->get_payload(message,
-													SECURITY_ASSOCIATION_V1);
+													PLV1_SECURITY_ASSOCIATION);
 			if (!sa_payload)
 			{
 				DBG1(DBG_IKE, "SA payload missing");
@@ -627,7 +627,7 @@ METHOD(task_t, process_i, status_t,
 			id_payload_t *id_payload;
 			identification_t *id, *cid;
 
-			id_payload = (id_payload_t*)message->get_payload(message, ID_V1);
+			id_payload = (id_payload_t*)message->get_payload(message, PLV1_ID);
 			if (!id_payload)
 			{
 				DBG1(DBG_IKE, "IDir payload missing");
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
index 17fe025..94026b9 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.c
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -107,7 +107,7 @@ static configuration_attribute_t *build_vip(host_t *vip)
 			chunk = chunk_cata("cc", chunk, prefix);
 		}
 	}
-	return configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
+	return configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
 												type, chunk);
 }
 
@@ -139,11 +139,8 @@ static void handle_attribute(private_mode_config_t *this,
 	handler = hydra->attributes->handle(hydra->attributes,
 							this->ike_sa->get_other_id(this->ike_sa), handler,
 							ca->get_type(ca), ca->get_chunk(ca));
-	if (handler)
-	{
-		this->ike_sa->add_configuration_attribute(this->ike_sa,
-				handler, ca->get_type(ca), ca->get_chunk(ca));
-	}
+	this->ike_sa->add_configuration_attribute(this->ike_sa,
+							handler, ca->get_type(ca), ca->get_chunk(ca));
 }
 
 /**
@@ -222,7 +219,7 @@ static void process_payloads(private_mode_config_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == CONFIGURATION_V1)
+		if (payload->get_type(payload) == PLV1_CONFIGURATION)
 		{
 			cp_payload_t *cp = (cp_payload_t*)payload;
 			configuration_attribute_t *ca;
@@ -273,7 +270,7 @@ static void add_attribute(private_mode_config_t *this, cp_payload_t *cp,
 	entry_t *entry;
 
 	cp->add_attribute(cp,
-			configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
+			configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
 												 type, data));
 	INIT(entry,
 		.type = type,
@@ -296,7 +293,7 @@ static status_t build_request(private_mode_config_t *this, message_t *message)
 	linked_list_t *vips;
 	host_t *host;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
 
 	vips = linked_list_create();
 
@@ -360,7 +357,7 @@ static status_t build_set(private_mode_config_t *this, message_t *message)
 	host_t *any4, *any6, *found;
 	char *name;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_SET);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_SET);
 
 	id = this->ike_sa->get_other_eap_id(this->ike_sa);
 	config = this->ike_sa->get_peer_cfg(this->ike_sa);
@@ -396,6 +393,8 @@ static status_t build_set(private_mode_config_t *this, message_t *message)
 	any4->destroy(any4);
 	any6->destroy(any6);
 
+	charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
+
 	/* query registered providers for additional attributes to include */
 	pools = linked_list_create_from_enumerator(
 									config->create_pool_enumerator(config));
@@ -442,6 +441,8 @@ static void install_vips(private_mode_config_t *this)
 		}
 	}
 	enumerator->destroy(enumerator);
+
+	charon->bus->handle_vips(charon->bus, this->ike_sa, TRUE);
 }
 
 METHOD(task_t, process_r, status_t,
@@ -470,7 +471,7 @@ static status_t build_reply(private_mode_config_t *this, message_t *message)
 	linked_list_t *vips, *pools;
 	host_t *requested;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
 
 	id = this->ike_sa->get_other_eap_id(this->ike_sa);
 	config = this->ike_sa->get_peer_cfg(this->ike_sa);
@@ -505,13 +506,15 @@ static status_t build_reply(private_mode_config_t *this, message_t *message)
 	}
 	enumerator->destroy(enumerator);
 
+	charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
+
 	/* query registered providers for additional attributes to include */
 	enumerator = hydra->attributes->create_responder_enumerator(
 											hydra->attributes, pools, id, vips);
 	while (enumerator->enumerate(enumerator, &type, &value))
 	{
 		cp->add_attribute(cp,
-			configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
+			configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
 												 type, value));
 	}
 	enumerator->destroy(enumerator);
@@ -535,7 +538,7 @@ static status_t build_ack(private_mode_config_t *this, message_t *message)
 	configuration_attribute_type_t type;
 	entry_t *entry;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_ACK);
 
 	/* return empty attributes for installed IPs */
 
@@ -552,7 +555,7 @@ static status_t build_ack(private_mode_config_t *this, message_t *message)
 			type = INTERNAL_IP4_ADDRESS;
 		}
 		cp->add_attribute(cp, configuration_attribute_create_chunk(
-								CONFIGURATION_ATTRIBUTE_V1, type, chunk_empty));
+								PLV1_CONFIGURATION_ATTRIBUTE, type, chunk_empty));
 	}
 	enumerator->destroy(enumerator);
 
@@ -560,7 +563,7 @@ static status_t build_ack(private_mode_config_t *this, message_t *message)
 	while (enumerator->enumerate(enumerator, &entry))
 	{
 		cp->add_attribute(cp,
-			configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
+			configuration_attribute_create_chunk(PLV1_CONFIGURATION_ATTRIBUTE,
 												 entry->type, chunk_empty));
 	}
 	enumerator->destroy(enumerator);
diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.c b/src/libcharon/sa/ikev1/tasks/quick_delete.c
index 605c10c..499081c 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_delete.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_delete.c
@@ -177,7 +177,7 @@ METHOD(task_t, build_i, status_t,
 		DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
 			 protocol_id_names, this->protocol, ntohl(this->spi));
 
-		delete_payload = delete_payload_create(DELETE_V1, this->protocol);
+		delete_payload = delete_payload_create(PLV1_DELETE, this->protocol);
 		delete_payload->add_spi(delete_payload, this->spi);
 		message->add_payload(message, &delete_payload->payload_interface);
 
@@ -205,7 +205,7 @@ METHOD(task_t, process_r, status_t,
 	payloads = message->create_payload_enumerator(message);
 	while (payloads->enumerate(payloads, &payload))
 	{
-		if (payload->get_type(payload) == DELETE_V1)
+		if (payload->get_type(payload) == PLV1_DELETE)
 		{
 			delete_payload = (delete_payload_t*)payload;
 			protocol = delete_payload->get_protocol_id(delete_payload);
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 6e7da98..e627368 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -427,7 +427,7 @@ static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
 	}
 	nonceg->destroy(nonceg);
 
-	nonce_payload = nonce_payload_create(NONCE_V1);
+	nonce_payload = nonce_payload_create(PLV1_NONCE);
 	nonce_payload->set_nonce(nonce_payload, *nonce);
 	message->add_payload(message, &nonce_payload->payload_interface);
 
@@ -442,7 +442,7 @@ static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
 {
 	nonce_payload_t *nonce_payload;
 
-	nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
+	nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
 	if (!nonce_payload)
 	{
 		DBG1(DBG_IKE, "NONCE payload missing in message");
@@ -460,7 +460,7 @@ static void add_ke(private_quick_mode_t *this, message_t *message)
 {
 	ke_payload_t *ke_payload;
 
-	ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
+	ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE, this->dh);
 	message->add_payload(message, &ke_payload->payload_interface);
 }
 
@@ -471,7 +471,7 @@ static bool get_ke(private_quick_mode_t *this, message_t *message)
 {
 	ke_payload_t *ke_payload;
 
-	ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
+	ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
 	if (!ke_payload)
 	{
 		DBG1(DBG_IKE, "KE payload missing");
@@ -502,7 +502,7 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
 	else
 	{
 		DBG1(DBG_IKE, "%s traffic selector missing in configuration",
-			 local ? "local" : "local");
+			 local ? "local" : "remote");
 		ts = NULL;
 	}
 	list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
@@ -537,7 +537,7 @@ static bool get_ts(private_quick_mode_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == ID_V1)
+		if (payload->get_type(payload) == PLV1_ID)
 		{
 			id_payload = (id_payload_t*)payload;
 
@@ -640,9 +640,9 @@ static payload_type_t get_nat_oa_payload_type(ike_sa_t *ike_sa)
 {
 	if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
 	{
-		return NAT_OA_DRAFT_00_03_V1;
+		return PLV1_NAT_OA_DRAFT_00_03;
 	}
-	return NAT_OA_V1;
+	return PLV1_NAT_OA;
 }
 
 /**
@@ -726,7 +726,7 @@ static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
 {
 	notify_payload_t *notify;
 
-	notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
+	notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
 														  this->proto, type);
 	notify->set_spi(notify, this->spi_i);
 
@@ -917,7 +917,7 @@ static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY_V1)
+		if (payload->get_type(payload) == PLV1_NOTIFY)
 		{
 			notify_payload_t *notify;
 			notify_type_t type;
@@ -1000,7 +1000,7 @@ METHOD(task_t, process_r, status_t,
 			bool private;
 
 			sa_payload = (sa_payload_t*)message->get_payload(message,
-													SECURITY_ASSOCIATION_V1);
+													PLV1_SECURITY_ASSOCIATION);
 			if (!sa_payload)
 			{
 				DBG1(DBG_IKE, "sa payload missing");
@@ -1215,7 +1215,7 @@ METHOD(task_t, process_i, status_t,
 			bool private;
 
 			sa_payload = (sa_payload_t*)message->get_payload(message,
-													SECURITY_ASSOCIATION_V1);
+													PLV1_SECURITY_ASSOCIATION);
 			if (!sa_payload)
 			{
 				DBG1(DBG_IKE, "sa payload missing");
diff --git a/src/libcharon/sa/ikev1/tasks/xauth.c b/src/libcharon/sa/ikev1/tasks/xauth.c
index f5555ec..bdc5d67 100644
--- a/src/libcharon/sa/ikev1/tasks/xauth.c
+++ b/src/libcharon/sa/ikev1/tasks/xauth.c
@@ -277,7 +277,7 @@ METHOD(task_t, build_i_status, status_t,
 {
 	cp_payload_t *cp;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_SET);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_SET);
 	cp->add_attribute(cp,
 			configuration_attribute_create_value(XAUTH_STATUS, this->status));
 
@@ -291,7 +291,7 @@ METHOD(task_t, process_i_status, status_t,
 {
 	cp_payload_t *cp;
 
-	cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
+	cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
 	if (!cp || cp->get_type(cp) != CFG_ACK)
 	{
 		DBG1(DBG_IKE, "received invalid XAUTH status response");
@@ -354,11 +354,11 @@ METHOD(task_t, build_r_ack, status_t,
 {
 	cp_payload_t *cp;
 
-	cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK);
+	cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_ACK);
 	cp->set_identifier(cp, this->identifier);
 	cp->add_attribute(cp,
 			configuration_attribute_create_chunk(
-					CONFIGURATION_ATTRIBUTE_V1, XAUTH_STATUS, chunk_empty));
+					PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_STATUS, chunk_empty));
 
 	message->add_payload(message, (payload_t *)cp);
 
@@ -382,7 +382,7 @@ METHOD(task_t, process_r, status_t,
 			return NEED_MORE;
 		}
 	}
-	cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
+	cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
 	if (!cp)
 	{
 		DBG1(DBG_IKE, "configuration payload missing in XAuth request");
@@ -438,7 +438,7 @@ METHOD(task_t, build_r, status_t,
 {
 	if (!this->cp)
 	{	/* send empty reply if building data failed */
-		this->cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
+		this->cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
 	}
 	message->add_payload(message, (payload_t *)this->cp);
 	this->cp = NULL;
@@ -451,7 +451,7 @@ METHOD(task_t, process_i, status_t,
 	identification_t *id;
 	cp_payload_t *cp;
 
-	cp = (cp_payload_t*)message->get_payload(message, CONFIGURATION_V1);
+	cp = (cp_payload_t*)message->get_payload(message, PLV1_CONFIGURATION);
 	if (!cp)
 	{
 		DBG1(DBG_IKE, "configuration payload missing in XAuth response");
@@ -463,12 +463,6 @@ METHOD(task_t, process_i, status_t,
 			return NEED_MORE;
 		case SUCCESS:
 			id = this->xauth->get_identity(this->xauth);
-			if (this->user && !id->matches(id, this->user))
-			{
-				DBG1(DBG_IKE, "XAuth username '%Y' does not match to "
-					 "configured username '%Y'", id, this->user);
-				break;
-			}
 			DBG1(DBG_IKE, "XAuth authentication of '%Y' successful", id);
 			if (add_auth_cfg(this, id, FALSE) && allowed(this))
 			{
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index b8359cc..eed6d19 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -450,7 +450,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
 	keymat_v2_t *keymat;
 
 	auth_payload = (auth_payload_t*)message->get_payload(message,
-														 AUTHENTICATION);
+														 PLV2_AUTH);
 	if (!auth_payload)
 	{
 		DBG1(DBG_IKE, "AUTH payload missing");
@@ -532,7 +532,7 @@ METHOD(authenticator_t, process_server, status_t,
 	else
 	{
 		eap_payload = (eap_payload_t*)message->get_payload(message,
-													EXTENSIBLE_AUTHENTICATION);
+													PLV2_EAP);
 		if (!eap_payload)
 		{
 			return FAILED;
@@ -590,7 +590,7 @@ METHOD(authenticator_t, process_client, status_t,
 	}
 
 	eap_payload = (eap_payload_t*)message->get_payload(message,
-													EXTENSIBLE_AUTHENTICATION);
+													PLV2_EAP);
 	if (eap_payload)
 	{
 		switch (eap_payload->get_code(eap_payload))
diff --git a/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
index 997efe3..c6a4b6b 100644
--- a/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
@@ -103,7 +103,7 @@ METHOD(authenticator_t, process, status_t,
 	int keys_found = 0;
 	keymat_v2_t *keymat;
 
-	auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+	auth_payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
 	if (!auth_payload)
 	{
 		return FAILED;
diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 5ceff40..6fb14bc 100644
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -147,7 +147,7 @@ METHOD(authenticator_t, process, status_t,
 	status_t status = NOT_FOUND;
 	keymat_v2_t *keymat;
 
-	auth_payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+	auth_payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
 	if (!auth_payload)
 	{
 		return FAILED;
diff --git a/src/libcharon/sa/ikev2/connect_manager.c b/src/libcharon/sa/ikev2/connect_manager.c
index c4e5ea7..161c4fd 100644
--- a/src/libcharon/sa/ikev2/connect_manager.c
+++ b/src/libcharon/sa/ikev2/connect_manager.c
@@ -748,7 +748,7 @@ static status_t process_payloads(message_t *message, check_t *check)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) != NOTIFY)
+		if (payload->get_type(payload) != PLV2_NOTIFY)
 		{
 			DBG1(DBG_IKE, "ignoring payload of type '%N' while processing "
 				 "connectivity check", payload_type_names,
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index a5252ab..ada798b 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -792,7 +792,7 @@ static status_t process_request(private_task_manager_t *this,
 				{
 					switch (payload->get_type(payload))
 					{
-						case NOTIFY:
+						case PLV2_NOTIFY:
 						{	/* if we find a rekey notify, its CHILD_SA rekeying */
 							notify = (notify_payload_t*)payload;
 							if (notify->get_notify_type(notify) == REKEY_SA &&
@@ -803,8 +803,8 @@ static status_t process_request(private_task_manager_t *this,
 							}
 							break;
 						}
-						case TRAFFIC_SELECTOR_INITIATOR:
-						case TRAFFIC_SELECTOR_RESPONDER:
+						case PLV2_TS_INITIATOR:
+						case PLV2_TS_RESPONDER:
 						{	/* if we don't find a TS, its IKE rekeying */
 							ts_found = TRUE;
 							break;
@@ -842,7 +842,7 @@ static status_t process_request(private_task_manager_t *this,
 				{
 					switch (payload->get_type(payload))
 					{
-						case NOTIFY:
+						case PLV2_NOTIFY:
 						{
 							notify = (notify_payload_t*)payload;
 							switch (notify->get_notify_type(notify))
@@ -875,7 +875,7 @@ static status_t process_request(private_task_manager_t *this,
 							}
 							break;
 						}
-						case DELETE:
+						case PLV2_DELETE:
 						{
 							delete = (delete_payload_t*)payload;
 							if (delete->get_protocol_id(delete) == PROTO_IKE)
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index df7bc96..a1f01c2 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -187,7 +187,7 @@ static status_t get_nonce(message_t *message, chunk_t *nonce)
 {
 	nonce_payload_t *payload;
 
-	payload = (nonce_payload_t*)message->get_payload(message, NONCE);
+	payload = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
 	if (payload == NULL)
 	{
 		return FAILED;
@@ -731,7 +731,7 @@ static void build_payloads(private_child_create_t *this, message_t *message)
 	/* add nonce payload if not in IKE_AUTH */
 	if (message->get_exchange_type(message) == CREATE_CHILD_SA)
 	{
-		nonce_payload = nonce_payload_create(NONCE);
+		nonce_payload = nonce_payload_create(PLV2_NONCE);
 		nonce_payload->set_nonce(nonce_payload, this->my_nonce);
 		message->add_payload(message, (payload_t*)nonce_payload);
 	}
@@ -739,7 +739,7 @@ static void build_payloads(private_child_create_t *this, message_t *message)
 	/* diffie hellman exchange, if PFS enabled */
 	if (this->dh)
 	{
-		ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE,
+		ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE,
 														   this->dh);
 		message->add_payload(message, (payload_t*)ke_payload);
 	}
@@ -866,11 +866,11 @@ static void process_payloads(private_child_create_t *this, message_t *message)
 	{
 		switch (payload->get_type(payload))
 		{
-			case SECURITY_ASSOCIATION:
+			case PLV2_SECURITY_ASSOCIATION:
 				sa_payload = (sa_payload_t*)payload;
 				this->proposals = sa_payload->get_proposals(sa_payload);
 				break;
-			case KEY_EXCHANGE:
+			case PLV2_KEY_EXCHANGE:
 				ke_payload = (ke_payload_t*)payload;
 				if (!this->initiator)
 				{
@@ -884,15 +884,15 @@ static void process_payloads(private_child_create_t *this, message_t *message)
 								ke_payload->get_key_exchange_data(ke_payload));
 				}
 				break;
-			case TRAFFIC_SELECTOR_INITIATOR:
+			case PLV2_TS_INITIATOR:
 				ts_payload = (ts_payload_t*)payload;
 				this->tsi = ts_payload->get_traffic_selectors(ts_payload);
 				break;
-			case TRAFFIC_SELECTOR_RESPONDER:
+			case PLV2_TS_RESPONDER:
 				ts_payload = (ts_payload_t*)payload;
 				this->tsr = ts_payload->get_traffic_selectors(ts_payload);
 				break;
-			case NOTIFY:
+			case PLV2_NOTIFY:
 				handle_notify(this, (notify_payload_t*)payload);
 				break;
 			default:
@@ -950,7 +950,7 @@ METHOD(task_t, build_i, status_t,
 	/* check if we want a virtual IP, but don't have one */
 	list = linked_list_create();
 	peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-	if (!this->reqid)
+	if (!this->rekey)
 	{
 		enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
 		while (enumerator->enumerate(enumerator, &vip))
@@ -1192,6 +1192,12 @@ METHOD(task_t, build_r, status_t,
 		message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
 		return SUCCESS;
 	}
+	if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
+	{
+		DBG1(DBG_IKE, "unable to create CHILD_SA while deleting IKE_SA");
+		message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
+		return SUCCESS;
+	}
 
 	if (this->config == NULL)
 	{
@@ -1211,7 +1217,7 @@ METHOD(task_t, build_r, status_t,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY)
+		if (payload->get_type(payload) == PLV2_NOTIFY)
 		{
 			notify_payload_t *notify = (notify_payload_t*)payload;
 
@@ -1313,7 +1319,7 @@ METHOD(task_t, build_i_delete, status_t,
 
 		proto = this->proposal->get_protocol(this->proposal);
 		spi = this->child_sa->get_spi(this->child_sa, TRUE);
-		del = delete_payload_create(DELETE, proto);
+		del = delete_payload_create(PLV2_DELETE, proto);
 		del->add_spi(del, spi);
 		message->add_payload(message, (payload_t*)del);
 
@@ -1362,7 +1368,7 @@ METHOD(task_t, process_i, status_t,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY)
+		if (payload->get_type(payload) == PLV2_NOTIFY)
 		{
 			notify_payload_t *notify = (notify_payload_t*)payload;
 			notify_type_t type = notify->get_notify_type(notify);
diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c
index 88b032c..2b16974 100644
--- a/src/libcharon/sa/ikev2/tasks/child_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/child_delete.c
@@ -93,7 +93,7 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
 			case PROTO_ESP:
 				if (esp == NULL)
 				{
-					esp = delete_payload_create(DELETE, PROTO_ESP);
+					esp = delete_payload_create(PLV2_DELETE, PROTO_ESP);
 					message->add_payload(message, (payload_t*)esp);
 				}
 				esp->add_spi(esp, spi);
@@ -103,7 +103,7 @@ static void build_payloads(private_child_delete_t *this, message_t *message)
 			case PROTO_AH:
 				if (ah == NULL)
 				{
-					ah = delete_payload_create(DELETE, PROTO_AH);
+					ah = delete_payload_create(PLV2_DELETE, PROTO_AH);
 					message->add_payload(message, (payload_t*)ah);
 				}
 				ah->add_spi(ah, spi);
@@ -133,7 +133,7 @@ static void process_payloads(private_child_delete_t *this, message_t *message)
 	payloads = message->create_payload_enumerator(message);
 	while (payloads->enumerate(payloads, &payload))
 	{
-		if (payload->get_type(payload) == DELETE)
+		if (payload->get_type(payload) == PLV2_DELETE)
 		{
 			delete_payload = (delete_payload_t*)payload;
 			protocol = delete_payload->get_protocol_id(delete_payload);
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index d2003bb..db87282 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -171,7 +171,7 @@ METHOD(task_t, build_i, status_t,
 	config = this->child_sa->get_config(this->child_sa);
 
 	/* we just need the rekey notify ... */
-	notify = notify_payload_create_from_protocol_and_type(NOTIFY,
+	notify = notify_payload_create_from_protocol_and_type(PLV2_NOTIFY,
 													this->protocol, REKEY_SA);
 	notify->set_spi(notify, this->spi);
 	message->add_payload(message, (payload_t*)notify);
@@ -228,7 +228,7 @@ METHOD(task_t, build_r, status_t,
 	this->child_create->set_config(this->child_create, config->get_ref(config));
 	this->child_create->task.build(&this->child_create->task, message);
 
-	if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
+	if (message->get_payload(message, PLV2_SECURITY_ASSOCIATION) == NULL)
 	{
 		/* rekeying failed, reuse old child */
 		this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
@@ -332,7 +332,7 @@ METHOD(task_t, process_i, status_t,
 		this->child_create->task.migrate(&this->child_create->task, this->ike_sa);
 		return NEED_MORE;
 	}
-	if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
+	if (message->get_payload(message, PLV2_SECURITY_ASSOCIATION) == NULL)
 	{
 		/* establishing new child failed, reuse old. but not when we
 		 * received a delete in the meantime */
diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c
index 800dab0..bf747a4 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_auth.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c
@@ -132,7 +132,7 @@ static status_t collect_my_init_data(private_ike_auth_t *this,
 	nonce_payload_t *nonce;
 
 	/* get the nonce that was generated in ike_init */
-	nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
+	nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
 	if (nonce == NULL)
 	{
 		return FAILED;
@@ -158,7 +158,7 @@ static status_t collect_other_init_data(private_ike_auth_t *this,
 	nonce_payload_t *nonce;
 
 	/* get the nonce that was generated in ike_init */
-	nonce = (nonce_payload_t*)message->get_payload(message, NONCE);
+	nonce = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
 	if (nonce == NULL)
 	{
 		return FAILED;
@@ -433,7 +433,7 @@ METHOD(task_t, build_i, status_t,
 			{
 				this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr));
 				id_payload = id_payload_create_from_identification(
-															ID_RESPONDER, idr);
+															PLV2_ID_RESPONDER, idr);
 				message->add_payload(message, (payload_t*)id_payload);
 			}
 		}
@@ -451,7 +451,7 @@ METHOD(task_t, build_i, status_t,
 			cfg->add(cfg, AUTH_RULE_IDENTITY, idi);
 		}
 		this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
-		id_payload = id_payload_create_from_identification(ID_INITIATOR, idi);
+		id_payload = id_payload_create_from_identification(PLV2_ID_INITIATOR, idi);
 		get_reserved_id_bytes(this, id_payload);
 		message->add_payload(message, (payload_t*)id_payload);
 
@@ -498,7 +498,7 @@ METHOD(task_t, build_i, status_t,
 	/* check for additional authentication rounds */
 	if (do_another_auth(this))
 	{
-		if (message->get_payload(message, AUTHENTICATION))
+		if (message->get_payload(message, PLV2_AUTH))
 		{
 			message->add_notify(message, FALSE, ANOTHER_AUTH_FOLLOWS, chunk_empty);
 		}
@@ -525,7 +525,7 @@ METHOD(task_t, process_r, status_t,
 	if (this->my_auth == NULL && this->do_another_auth)
 	{
 		/* handle (optional) IDr payload, apply proposed identity */
-		id_payload = (id_payload_t*)message->get_payload(message, ID_RESPONDER);
+		id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_RESPONDER);
 		if (id_payload)
 		{
 			id = id_payload->get_identification(id_payload);
@@ -558,7 +558,7 @@ METHOD(task_t, process_r, status_t,
 	if (this->other_auth == NULL)
 	{
 		/* handle IDi payload */
-		id_payload = (id_payload_t*)message->get_payload(message, ID_INITIATOR);
+		id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_INITIATOR);
 		if (!id_payload)
 		{
 			DBG1(DBG_IKE, "IDi payload missing");
@@ -578,7 +578,7 @@ METHOD(task_t, process_r, status_t,
 				return NEED_MORE;
 			}
 		}
-		if (message->get_payload(message, AUTHENTICATION) == NULL)
+		if (message->get_payload(message, PLV2_AUTH) == NULL)
 		{	/* before authenticating with EAP, we need a EAP config */
 			cand = get_auth_cfg(this, FALSE);
 			while (!cand || (
@@ -631,7 +631,7 @@ METHOD(task_t, process_r, status_t,
 			this->other_auth = NULL;
 			break;
 		case NEED_MORE:
-			if (message->get_payload(message, AUTHENTICATION))
+			if (message->get_payload(message, PLV2_AUTH))
 			{	/* AUTH verification successful, but another build() needed */
 				break;
 			}
@@ -733,7 +733,7 @@ METHOD(task_t, build_r, status_t,
 			}
 		}
 
-		id_payload = id_payload_create_from_identification(ID_RESPONDER, id);
+		id_payload = id_payload_create_from_identification(PLV2_ID_RESPONDER, id);
 		get_reserved_id_bytes(this, id_payload);
 		message->add_payload(message, (payload_t*)id_payload);
 
@@ -780,7 +780,7 @@ METHOD(task_t, build_r, status_t,
 			case NEED_MORE:
 				break;
 			default:
-				if (message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
+				if (message->get_payload(message, PLV2_EAP))
 				{	/* skip AUTHENTICATION_FAILED if we have EAP_FAILURE */
 					goto peer_auth_failed_no_notify;
 				}
@@ -900,7 +900,7 @@ METHOD(task_t, process_i, status_t,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY)
+		if (payload->get_type(payload) == PLV2_NOTIFY)
 		{
 			notify_payload_t *notify = (notify_payload_t*)payload;
 			notify_type_t type = notify->get_notify_type(notify);
@@ -956,7 +956,7 @@ METHOD(task_t, process_i, status_t,
 
 			/* handle IDr payload */
 			id_payload = (id_payload_t*)message->get_payload(message,
-															 ID_RESPONDER);
+															 PLV2_ID_RESPONDER);
 			if (!id_payload)
 			{
 				DBG1(DBG_IKE, "IDr payload missing");
@@ -968,7 +968,7 @@ METHOD(task_t, process_i, status_t,
 			cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
 			cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
 
-			if (message->get_payload(message, AUTHENTICATION))
+			if (message->get_payload(message, PLV2_AUTH))
 			{
 				/* verify authentication data */
 				this->other_auth = authenticator_create_verifier(this->ike_sa,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_cert_post.c b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c
index 6dbc4de..5a9e08d 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_cert_post.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c
@@ -63,14 +63,14 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
 
 	if (!this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL))
 	{
-		return cert_payload_create_from_cert(CERTIFICATE, cert);
+		return cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 	}
 
 	hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
 	if (!hasher)
 	{
 		DBG1(DBG_IKE, "unable to use hash-and-url: sha1 not supported");
-		return cert_payload_create_from_cert(CERTIFICATE, cert);
+		return cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 	}
 
 	if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
@@ -83,7 +83,7 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
 	{
 		hasher->destroy(hasher);
 		chunk_free(&encoded);
-		return cert_payload_create_from_cert(CERTIFICATE, cert);
+		return cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 	}
 	chunk_free(&encoded);
 	hasher->destroy(hasher);
@@ -97,7 +97,7 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
 	}
 	else
 	{
-		payload = cert_payload_create_from_cert(CERTIFICATE, cert);
+		payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 	}
 	enumerator->destroy(enumerator);
 	chunk_free(&hash);
@@ -145,7 +145,7 @@ static void add_im_certs(private_ike_cert_post_t *this, auth_cfg_t *auth,
 	{
 		if (type == AUTH_RULE_IM_CERT)
 		{
-			payload = cert_payload_create_from_cert(CERTIFICATE, cert);
+			payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 			if (payload)
 			{
 				DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
@@ -187,7 +187,7 @@ static void add_attribute_certs(private_ike_cert_post_t *this,
 			if (id && id->equals(id, subject->get_issuer(subject)) &&
 				cert->get_validity(cert, NULL, NULL, NULL))
 			{
-				payload = cert_payload_create_from_cert(CERTIFICATE, cert);
+				payload = cert_payload_create_from_cert(PLV2_CERTIFICATE, cert);
 				if (payload)
 				{
 					DBG1(DBG_IKE, "sending attribute certificate "
@@ -210,7 +210,7 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
 	auth_payload_t *payload;
 	auth_cfg_t *auth;
 
-	payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
+	payload = (auth_payload_t*)message->get_payload(message, PLV2_AUTH);
 	peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
 	if (!peer_cfg || !payload || payload->get_auth_method(payload) == AUTH_PSK)
 	{	/* no CERT payload for EAP/PSK */
diff --git a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c
index 558b1e9..0dac975 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c
@@ -138,10 +138,10 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
 	{
 		switch (payload->get_type(payload))
 		{
-			case CERTIFICATE_REQUEST:
+			case PLV2_CERTREQ:
 				process_certreq(this, (certreq_payload_t*)payload, auth);
 				break;
-			case NOTIFY:
+			case PLV2_NOTIFY:
 				process_notify(this, (notify_payload_t*)payload);
 				break;
 			default:
@@ -298,7 +298,7 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == CERTIFICATE)
+		if (payload->get_type(payload) == PLV2_CERTIFICATE)
 		{
 			cert_payload_t *cert_payload;
 			cert_encoding_t encoding;
@@ -469,7 +469,7 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
 static bool final_auth(message_t *message)
 {
 	/* we check for an AUTH payload without a ANOTHER_AUTH_FOLLOWS notify */
-	if (message->get_payload(message, AUTHENTICATION) == NULL)
+	if (message->get_payload(message, PLV2_AUTH) == NULL)
 	{
 		return FALSE;
 	}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c
index 17132fe..da06e2a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_config.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_config.c
@@ -98,7 +98,7 @@ static configuration_attribute_t *build_vip(host_t *vip)
 			chunk = chunk_cata("cc", chunk, prefix);
 		}
 	}
-	return configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE,
+	return configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
 												type, chunk);
 }
 
@@ -130,11 +130,8 @@ static void handle_attribute(private_ike_config_t *this,
 	handler = hydra->attributes->handle(hydra->attributes,
 							this->ike_sa->get_other_id(this->ike_sa), handler,
 							ca->get_type(ca), ca->get_chunk(ca));
-	if (handler)
-	{
-		this->ike_sa->add_configuration_attribute(this->ike_sa,
-				handler, ca->get_type(ca), ca->get_chunk(ca));
-	}
+	this->ike_sa->add_configuration_attribute(this->ike_sa,
+							handler, ca->get_type(ca), ca->get_chunk(ca));
 }
 
 /**
@@ -200,7 +197,7 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == CONFIGURATION)
+		if (payload->get_type(payload) == PLV2_CONFIGURATION)
 		{
 			cp_payload_t *cp = (cp_payload_t*)payload;
 			configuration_attribute_t *ca;
@@ -268,7 +265,7 @@ METHOD(task_t, build_i, status_t,
 
 		if (vips->get_count(vips))
 		{
-			cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
+			cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST);
 			enumerator = vips->create_enumerator(vips);
 			while (enumerator->enumerate(enumerator, &host))
 			{
@@ -288,11 +285,11 @@ METHOD(task_t, build_i, status_t,
 			/* create configuration attribute */
 			DBG2(DBG_IKE, "building %N attribute",
 				 configuration_attribute_type_names, type);
-			ca = configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE,
+			ca = configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
 													  type, data);
 			if (!cp)
 			{
-				cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
+				cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST);
 			}
 			cp->add_attribute(cp, ca);
 
@@ -363,7 +360,7 @@ METHOD(task_t, build_r, status_t,
 				this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
 				if (!cp)
 				{
-					cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
+					cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REPLY);
 				}
 				cp->add_attribute(cp, build_vip(found));
 				vips->insert_last(vips, found);
@@ -407,12 +404,12 @@ METHOD(task_t, build_r, status_t,
 		{
 			if (!cp)
 			{
-				cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
+				cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REPLY);
 			}
 			DBG2(DBG_IKE, "building %N attribute",
 				 configuration_attribute_type_names, type);
 			cp->add_attribute(cp,
-				configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE,
+				configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE,
 													 type, value));
 		}
 		enumerator->destroy(enumerator);
@@ -449,6 +446,8 @@ METHOD(task_t, process_i, status_t,
 			}
 		}
 		enumerator->destroy(enumerator);
+
+		charon->bus->handle_vips(charon->bus, this->ike_sa, TRUE);
 		return SUCCESS;
 	}
 	return NEED_MORE;
diff --git a/src/libcharon/sa/ikev2/tasks/ike_delete.c b/src/libcharon/sa/ikev2/tasks/ike_delete.c
index 9bc62bf..e972dba 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_delete.c
@@ -65,7 +65,7 @@ METHOD(task_t, build_i, status_t,
 		 this->ike_sa->get_other_host(this->ike_sa),
 		 this->ike_sa->get_other_id(this->ike_sa));
 
-	delete_payload = delete_payload_create(DELETE, PROTO_IKE);
+	delete_payload = delete_payload_create(PLV2_DELETE, PROTO_IKE);
 	message->add_payload(message, (payload_t*)delete_payload);
 
 	if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index 278bdc3..e3c18ea 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -147,9 +147,9 @@ static void build_payloads(private_ike_init_t *this, message_t *message)
 	}
 	message->add_payload(message, (payload_t*)sa_payload);
 
-	nonce_payload = nonce_payload_create(NONCE);
+	nonce_payload = nonce_payload_create(PLV2_NONCE);
 	nonce_payload->set_nonce(nonce_payload, this->my_nonce);
-	ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE, this->dh);
+	ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE, this->dh);
 
 	if (this->old_sa)
 	{	/* payload order differs if we are rekeying */
@@ -176,7 +176,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
 	{
 		switch (payload->get_type(payload))
 		{
-			case SECURITY_ASSOCIATION:
+			case PLV2_SECURITY_ASSOCIATION:
 			{
 				sa_payload_t *sa_payload = (sa_payload_t*)payload;
 				linked_list_t *proposal_list;
@@ -196,7 +196,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
 											  offsetof(proposal_t, destroy));
 				break;
 			}
-			case KEY_EXCHANGE:
+			case PLV2_KEY_EXCHANGE:
 			{
 				ke_payload_t *ke_payload = (ke_payload_t*)payload;
 
@@ -213,7 +213,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
 				}
 				break;
 			}
-			case NONCE:
+			case PLV2_NONCE:
 			{
 				nonce_payload_t *nonce_payload = (nonce_payload_t*)payload;
 
@@ -449,7 +449,7 @@ METHOD(task_t, process_i, status_t,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == NOTIFY)
+		if (payload->get_type(payload) == PLV2_NOTIFY)
 		{
 			notify_payload_t *notify = (notify_payload_t*)payload;
 			notify_type_t type = notify->get_notify_type(notify);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_me.c b/src/libcharon/sa/ikev2/tasks/ike_me.c
index 135c06d..a7e7505 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_me.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_me.c
@@ -171,7 +171,7 @@ static void process_payloads(private_ike_me_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) != NOTIFY)
+		if (payload->get_type(payload) != PLV2_NOTIFY)
 		{
 			continue;
 		}
@@ -277,7 +277,7 @@ METHOD(task_t, build_i, status_t,
 		{
 			rng_t *rng;
 			id_payload_t *id_payload;
-			id_payload = id_payload_create_from_identification(ID_PEER,
+			id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
 															   this->peer_id);
 			message->add_payload(message, (payload_t*)id_payload);
 
@@ -339,7 +339,7 @@ METHOD(task_t, process_r, status_t,
 		case ME_CONNECT:
 		{
 			id_payload_t *id_payload;
-			id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
+			id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
 			if (!id_payload)
 			{
 				DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
@@ -534,7 +534,7 @@ METHOD(task_t, build_i_ms, status_t,
 		case ME_CONNECT:
 		{
 			id_payload_t *id_payload;
-			id_payload = id_payload_create_from_identification(ID_PEER,
+			id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
 															   this->peer_id);
 			message->add_payload(message, (payload_t*)id_payload);
 
@@ -594,7 +594,7 @@ METHOD(task_t, process_r_ms, status_t,
 		case ME_CONNECT:
 		{
 			id_payload_t *id_payload;
-			id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
+			id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
 			if (!id_payload)
 			{
 				DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index ae3526f..00ca615 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -96,7 +96,7 @@ static void process_payloads(private_ike_mobike_t *this, message_t *message)
 		chunk_t data;
 		host_t *host;
 
-		if (payload->get_type(payload) != NOTIFY)
+		if (payload->get_type(payload) != PLV2_NOTIFY)
 		{
 			continue;
 		}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_natd.c b/src/libcharon/sa/ikev2/tasks/ike_natd.c
index 4fc968f..9e0eb68 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_natd.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_natd.c
@@ -172,7 +172,7 @@ static notify_payload_t *build_natd_payload(private_ike_natd_t *this,
 	{
 		return NULL;
 	}
-	notify = notify_payload_create(NOTIFY);
+	notify = notify_payload_create(PLV2_NOTIFY);
 	notify->set_notify_type(notify, type);
 	notify->set_notification_data(notify, hash);
 	chunk_free(&hash);
@@ -206,7 +206,7 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) != NOTIFY)
+		if (payload->get_type(payload) != PLV2_NOTIFY)
 		{
 			continue;
 		}
@@ -381,7 +381,7 @@ METHOD(task_t, build_r, status_t,
 
 	/* only add notifies on successful responses. */
 	if (message->get_exchange_type(message) == IKE_SA_INIT &&
-		message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
+		message->get_payload(message, PLV2_SECURITY_ASSOCIATION) == NULL)
 	{
 		return SUCCESS;
 	}
diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
index c3c6cf0..444ac6a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
@@ -83,7 +83,7 @@ static void establish_new(private_ike_rekey_t *this)
 			 this->ike_sa->get_other_host(this->ike_sa),
 			 this->ike_sa->get_other_id(this->ike_sa));
 
-		this->new_sa->inherit(this->new_sa, this->ike_sa);
+		this->new_sa->inherit_post(this->new_sa, this->ike_sa);
 		charon->bus->ike_rekey(charon->bus, this->ike_sa, this->new_sa);
 		charon->ike_sa_manager->checkin(charon->ike_sa_manager, this->new_sa);
 		this->new_sa = NULL;
@@ -124,8 +124,6 @@ METHOD(task_t, build_i, status_t,
 	private_ike_rekey_t *this, message_t *message)
 {
 	ike_version_t version;
-	peer_cfg_t *peer_cfg;
-	host_t *other_host;
 
 	/* create new SA only on first try */
 	if (this->new_sa == NULL)
@@ -137,10 +135,7 @@ METHOD(task_t, build_i, status_t,
 		{	/* shouldn't happen */
 			return FAILED;
 		}
-		peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-		other_host = this->ike_sa->get_other_host(this->ike_sa);
-		this->new_sa->set_peer_cfg(this->new_sa, peer_cfg);
-		this->new_sa->set_other_host(this->new_sa, other_host->clone(other_host));
+		this->new_sa->inherit_pre(this->new_sa, this->ike_sa);
 		this->ike_init = ike_init_create(this->new_sa, TRUE, this->ike_sa);
 		this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
 	}
@@ -153,7 +148,6 @@ METHOD(task_t, process_r, status_t,
 	private_ike_rekey_t *this, message_t *message)
 {
 	enumerator_t *enumerator;
-	peer_cfg_t *peer_cfg;
 	child_sa_t *child_sa;
 
 	if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
@@ -186,9 +180,7 @@ METHOD(task_t, process_r, status_t,
 	{	/* shouldn't happen */
 		return FAILED;
 	}
-
-	peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
-	this->new_sa->set_peer_cfg(this->new_sa, peer_cfg);
+	this->new_sa->inherit_pre(this->new_sa, this->ike_sa);
 	this->ike_init = ike_init_create(this->new_sa, FALSE, this->ike_sa);
 	this->ike_init->task.process(&this->ike_init->task, message);
 
diff --git a/src/libcharon/sa/ikev2/tasks/ike_vendor.c b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
index 16ac166..d536af2 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_vendor.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
@@ -92,7 +92,7 @@ METHOD(task_t, build, status_t,
 		if (vids[i].extension == EXT_STRONGSWAN && strongswan)
 		{
 			DBG2(DBG_IKE, "sending %s vendor ID", vids[i].desc);
-			vid = vendor_id_payload_create_data(VENDOR_ID,
+			vid = vendor_id_payload_create_data(PLV2_VENDOR_ID,
 										chunk_clone(get_vid_data(&vids[i])));
 			message->add_payload(message, &vid->payload_interface);
 		}
@@ -111,7 +111,7 @@ METHOD(task_t, process, status_t,
 	enumerator = message->create_payload_enumerator(message);
 	while (enumerator->enumerate(enumerator, &payload))
 	{
-		if (payload->get_type(payload) == VENDOR_ID)
+		if (payload->get_type(payload) == PLV2_VENDOR_ID)
 		{
 			vendor_id_payload_t *vid;
 			chunk_t data;
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index 94be7d4..73e1abb 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -49,11 +49,24 @@ static bool install_shunt_policy(child_cfg_t *child)
 	traffic_selector_t *my_ts, *other_ts;
 	host_t *host_any;
 	policy_type_t policy_type;
+	policy_priority_t policy_prio;
 	status_t status = SUCCESS;
 	ipsec_sa_cfg_t sa = { .mode = MODE_TRANSPORT };
 
-	policy_type = (child->get_mode(child) == MODE_PASS) ?
-											 POLICY_PASS : POLICY_DROP;
+	switch (child->get_mode(child))
+	{
+		case MODE_PASS:
+			policy_type = POLICY_PASS;
+			policy_prio = POLICY_PRIORITY_PASS;
+			break;
+		case MODE_DROP:
+			policy_type = POLICY_DROP;
+			policy_prio = POLICY_PRIORITY_FALLBACK;
+			break;
+		default:
+			return FALSE;
+	}
+
 	my_ts_list =    child->get_traffic_selectors(child, TRUE,  NULL, NULL);
 	other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, NULL);
 	host_any = host_create_any(AF_INET);
@@ -70,21 +83,21 @@ static bool install_shunt_policy(child_cfg_t *child)
 								hydra->kernel_interface, host_any, host_any,
 								my_ts, other_ts, POLICY_OUT, policy_type,
 								&sa, child->get_mark(child, FALSE),
-								POLICY_PRIORITY_DEFAULT);
+								policy_prio);
 
 			/* install in policy */
 			status |= hydra->kernel_interface->add_policy(
 								hydra->kernel_interface, host_any, host_any,
 								other_ts, my_ts, POLICY_IN, policy_type,
 								&sa, child->get_mark(child, TRUE),
-								POLICY_PRIORITY_DEFAULT);
+								policy_prio);
 
 			/* install forward policy */
 			status |= hydra->kernel_interface->add_policy(
 								hydra->kernel_interface, host_any, host_any,
 								other_ts, my_ts, POLICY_FWD, policy_type,
 								&sa, child->get_mark(child, TRUE),
-								POLICY_PRIORITY_DEFAULT);
+								policy_prio);
 		}
 		e_other_ts->destroy(e_other_ts);
 	}
@@ -137,8 +150,21 @@ static void uninstall_shunt_policy(child_cfg_t *child)
 	enumerator_t *e_my_ts, *e_other_ts;
 	linked_list_t *my_ts_list, *other_ts_list;
 	traffic_selector_t *my_ts, *other_ts;
+	policy_priority_t policy_prio;
 	status_t status = SUCCESS;
 
+	switch (child->get_mode(child))
+	{
+		case MODE_PASS:
+			policy_prio = POLICY_PRIORITY_PASS;
+			break;
+		case MODE_DROP:
+			policy_prio = POLICY_PRIORITY_FALLBACK;
+			break;
+		default:
+			return;
+	}
+
 	my_ts_list =    child->get_traffic_selectors(child, TRUE,  NULL, NULL);
 	other_ts_list = child->get_traffic_selectors(child, FALSE, NULL, NULL);
 
@@ -153,19 +179,19 @@ static void uninstall_shunt_policy(child_cfg_t *child)
 			status |= hydra->kernel_interface->del_policy(
 							hydra->kernel_interface, my_ts, other_ts,
 							POLICY_OUT, 0, child->get_mark(child, FALSE),
-							POLICY_PRIORITY_DEFAULT);
+							policy_prio);
 
 			/* uninstall in policy */
 			status |= hydra->kernel_interface->del_policy(
 							hydra->kernel_interface, other_ts, my_ts,
 							POLICY_IN, 0, child->get_mark(child, TRUE),
-							POLICY_PRIORITY_DEFAULT);
+							policy_prio);
 
 			/* uninstall forward policy */
 			status |= hydra->kernel_interface->del_policy(
 							hydra->kernel_interface, other_ts, my_ts,
 							POLICY_FWD, 0, child->get_mark(child, TRUE),
-							POLICY_PRIORITY_DEFAULT);
+							policy_prio);
 		}
 		e_other_ts->destroy(e_other_ts);
 	}
@@ -249,4 +275,3 @@ shunt_manager_t *shunt_manager_create()
 
 	return &this->public;
 }
-
diff --git a/src/libfast/Makefile.am b/src/libfast/Makefile.am
index 41a489b..48079c6 100644
--- a/src/libfast/Makefile.am
+++ b/src/libfast/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 	-I/usr/include/ClearSilver
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 AM_LDFLAGS = \
 	-no-undefined
diff --git a/src/libfast/Makefile.in b/src/libfast/Makefile.in
index f4405ae..cc4f6f7 100644
--- a/src/libfast/Makefile.in
+++ b/src/libfast/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I/usr/include/ClearSilver
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 AM_LDFLAGS = \
 	-no-undefined
diff --git a/src/libhydra/Makefile.am b/src/libhydra/Makefile.am
index f7ae37f..0c8ecda 100644
--- a/src/libhydra/Makefile.am
+++ b/src/libhydra/Makefile.am
@@ -14,6 +14,10 @@ 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}\" \
@@ -62,13 +66,6 @@ if MONOLITHIC
 endif
 endif
 
-if USE_KERNEL_KLIPS
-  SUBDIRS += plugins/kernel_klips
-if MONOLITHIC
-  libhydra_la_LIBADD += plugins/kernel_klips/libstrongswan-kernel-klips.la
-endif
-endif
-
 if USE_KERNEL_NETLINK
   SUBDIRS += plugins/kernel_netlink
 if MONOLITHIC
diff --git a/src/libhydra/Makefile.in b/src/libhydra/Makefile.in
index be3e36c..0b494b3 100644
--- a/src/libhydra/Makefile.in
+++ b/src/libhydra/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -78,20 +78,19 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at USE_ATTR_TRUE@am__append_1 = plugins/attr
- at MONOLITHIC_TRUE@@USE_ATTR_TRUE at am__append_2 = plugins/attr/libstrongswan-attr.la
- at USE_ATTR_SQL_TRUE@am__append_3 = plugins/attr_sql
- at MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE at am__append_4 = plugins/attr_sql/libstrongswan-attr-sql.la
- at USE_KERNEL_PFKEY_TRUE@am__append_5 = plugins/kernel_pfkey
- at MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE at am__append_6 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
- at USE_KERNEL_PFROUTE_TRUE@am__append_7 = plugins/kernel_pfroute
- at MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE at am__append_8 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
- at USE_KERNEL_KLIPS_TRUE@am__append_9 = plugins/kernel_klips
- at MONOLITHIC_TRUE@@USE_KERNEL_KLIPS_TRUE at am__append_10 = plugins/kernel_klips/libstrongswan-kernel-klips.la
- at USE_KERNEL_NETLINK_TRUE@am__append_11 = plugins/kernel_netlink
- at MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE at am__append_12 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
- at USE_RESOLVE_TRUE@am__append_13 = plugins/resolve
- at MONOLITHIC_TRUE@@USE_RESOLVE_TRUE at am__append_14 = plugins/resolve/libstrongswan-resolve.la
+ at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
+ at USE_ATTR_TRUE@am__append_2 = plugins/attr
+ at MONOLITHIC_TRUE@@USE_ATTR_TRUE at am__append_3 = plugins/attr/libstrongswan-attr.la
+ at USE_ATTR_SQL_TRUE@am__append_4 = plugins/attr_sql
+ at MONOLITHIC_TRUE@@USE_ATTR_SQL_TRUE at am__append_5 = plugins/attr_sql/libstrongswan-attr-sql.la
+ at USE_KERNEL_PFKEY_TRUE@am__append_6 = plugins/kernel_pfkey
+ at MONOLITHIC_TRUE@@USE_KERNEL_PFKEY_TRUE at am__append_7 = plugins/kernel_pfkey/libstrongswan-kernel-pfkey.la
+ at USE_KERNEL_PFROUTE_TRUE@am__append_8 = plugins/kernel_pfroute
+ at MONOLITHIC_TRUE@@USE_KERNEL_PFROUTE_TRUE at am__append_9 = plugins/kernel_pfroute/libstrongswan-kernel-pfroute.la
+ at USE_KERNEL_NETLINK_TRUE@am__append_10 = plugins/kernel_netlink
+ at MONOLITHIC_TRUE@@USE_KERNEL_NETLINK_TRUE at am__append_11 = plugins/kernel_netlink/libstrongswan-kernel-netlink.la
+ at USE_RESOLVE_TRUE@am__append_12 = plugins/resolve
+ at MONOLITHIC_TRUE@@USE_RESOLVE_TRUE at am__append_13 = plugins/resolve/libstrongswan-resolve.la
 subdir = src/libhydra
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -141,11 +140,12 @@ am__uninstall_files_from_dir = { \
   }
 am__installdirs = "$(DESTDIR)$(ipseclibdir)"
 LTLIBRARIES = $(ipseclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
 libhydra_la_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(am__append_2) $(am__append_4) $(am__append_6) \
-	$(am__append_8) $(am__append_10) $(am__append_12) \
-	$(am__append_14)
+	$(am__DEPENDENCIES_1) $(am__append_3) $(am__append_5) \
+	$(am__append_7) $(am__append_9) $(am__append_11) \
+	$(am__append_13)
 am__dirstamp = $(am__leading_dot)dirstamp
 am_libhydra_la_OBJECTS = hydra.lo attributes/attributes.lo \
 	attributes/attribute_manager.lo attributes/mem_pool.lo \
@@ -233,8 +233,7 @@ am__define_uniq_tagged_files = \
 ETAGS = etags
 CTAGS = ctags
 DIST_SUBDIRS = . plugins/attr plugins/attr_sql plugins/kernel_pfkey \
-	plugins/kernel_pfroute plugins/kernel_klips \
-	plugins/kernel_netlink plugins/resolve
+	plugins/kernel_pfroute plugins/kernel_netlink plugins/resolve
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 am__relativize = \
   dir0=`pwd`; \
@@ -323,6 +322,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -341,6 +341,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -368,6 +369,7 @@ 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@
@@ -459,6 +461,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -483,9 +486,9 @@ kernel/kernel_listener.h
 
 libhydra_la_LIBADD =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(am__append_2) $(am__append_4) $(am__append_6) \
-	$(am__append_8) $(am__append_10) $(am__append_12) \
-	$(am__append_14)
+	$(am__append_1) $(am__append_3) $(am__append_5) \
+	$(am__append_7) $(am__append_9) $(am__append_11) \
+	$(am__append_13)
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
@@ -496,17 +499,15 @@ AM_LDFLAGS = \
   -no-undefined
 
 EXTRA_DIST = Android.mk
- at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_1) $(am__append_3) \
- at MONOLITHIC_FALSE@	$(am__append_5) $(am__append_7) \
- at MONOLITHIC_FALSE@	$(am__append_9) $(am__append_11) \
- at MONOLITHIC_FALSE@	$(am__append_13)
+ at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_2) $(am__append_4) \
+ at MONOLITHIC_FALSE@	$(am__append_6) $(am__append_8) \
+ at MONOLITHIC_FALSE@	$(am__append_10) $(am__append_12)
 
 # build optional plugins
 ########################
- at MONOLITHIC_TRUE@SUBDIRS = $(am__append_1) $(am__append_3) \
- at MONOLITHIC_TRUE@	$(am__append_5) $(am__append_7) \
- at MONOLITHIC_TRUE@	$(am__append_9) $(am__append_11) \
- at MONOLITHIC_TRUE@	$(am__append_13)
+ at MONOLITHIC_TRUE@SUBDIRS = $(am__append_2) $(am__append_4) \
+ at MONOLITHIC_TRUE@	$(am__append_6) $(am__append_8) \
+ at MONOLITHIC_TRUE@	$(am__append_10) $(am__append_12)
 all: all-recursive
 
 .SUFFIXES:
diff --git a/src/libhydra/attributes/attributes.h b/src/libhydra/attributes/attributes.h
index c3c37cf..5d1e9f9 100644
--- a/src/libhydra/attributes/attributes.h
+++ b/src/libhydra/attributes/attributes.h
@@ -24,7 +24,7 @@
 
 typedef enum configuration_attribute_type_t configuration_attribute_type_t;
 
-#include <utils/enum.h>
+#include <utils/utils.h>
 
 /**
  * Type of the attribute, as in IKEv2 RFC 3.15.1 or IKEv1 ModeConfig.
diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c
index 3e34d20..3fa28e0 100644
--- a/src/libhydra/kernel/kernel_interface.c
+++ b/src/libhydra/kernel/kernel_interface.c
@@ -179,8 +179,9 @@ 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, bool initiator, bool encap, bool esn, bool inbound,
+	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,
 	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
 	if (!this->ipsec)
@@ -188,8 +189,9 @@ METHOD(kernel_interface_t, add_sa, status_t,
 		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, initiator, encap, esn, inbound, src_ts, dst_ts);
+				mark, tfc, lifetime, enc_alg, enc_key, int_alg, int_key, mode,
+				ipcomp, cpi, replay_window, initiator, encap, esn, inbound,
+				src_ts, dst_ts);
 }
 
 METHOD(kernel_interface_t, update_sa, status_t,
@@ -300,13 +302,13 @@ METHOD(kernel_interface_t, get_source_addr, host_t*,
 }
 
 METHOD(kernel_interface_t, get_nexthop, host_t*,
-	private_kernel_interface_t *this, host_t *dest, host_t *src)
+	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, src);
+	return this->net->get_nexthop(this->net, dest, prefix, src);
 }
 
 METHOD(kernel_interface_t, get_interface, bool,
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h
index cc47d3c..cd55038 100644
--- a/src/libhydra/kernel/kernel_interface.h
+++ b/src/libhydra/kernel/kernel_interface.h
@@ -69,6 +69,8 @@ enum kernel_feature_t {
 	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),
 };
 
 /**
@@ -145,6 +147,7 @@ struct kernel_interface_t {
 	 * @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
@@ -160,6 +163,7 @@ struct kernel_interface_t {
 						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,
 						traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
 
@@ -326,9 +330,12 @@ struct kernel_interface_t {
 	 * 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, host_t *src);
+	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
diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h
index 25f5b38..eec7401 100644
--- a/src/libhydra/kernel/kernel_ipsec.h
+++ b/src/libhydra/kernel/kernel_ipsec.h
@@ -101,6 +101,7 @@ struct kernel_ipsec_t {
 	 * @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
@@ -116,6 +117,7 @@ struct kernel_ipsec_t {
 						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,
 						traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
 
diff --git a/src/libhydra/kernel/kernel_net.h b/src/libhydra/kernel/kernel_net.h
index 8c448dd..4312c17 100644
--- a/src/libhydra/kernel/kernel_net.h
+++ b/src/libhydra/kernel/kernel_net.h
@@ -86,10 +86,12 @@ struct kernel_net_t {
 	 * 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, host_t *src);
+	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
diff --git a/src/libhydra/plugins/attr/Makefile.am b/src/libhydra/plugins/attr/Makefile.am
index 5989bea..5b899b8 100644
--- a/src/libhydra/plugins/attr/Makefile.am
+++ b/src/libhydra/plugins/attr/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-attr.la
diff --git a/src/libhydra/plugins/attr/Makefile.in b/src/libhydra/plugins/attr/Makefile.in
index ed13f1e..ddf2a44 100644
--- a/src/libhydra/plugins/attr/Makefile.in
+++ b/src/libhydra/plugins/attr/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-attr.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-attr.la
diff --git a/src/libhydra/plugins/attr_sql/Makefile.am b/src/libhydra/plugins/attr_sql/Makefile.am
index d126bb0..6e7eae5 100644
--- a/src/libhydra/plugins/attr_sql/Makefile.am
+++ b/src/libhydra/plugins/attr_sql/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-attr-sql.la
diff --git a/src/libhydra/plugins/attr_sql/Makefile.in b/src/libhydra/plugins/attr_sql/Makefile.in
index 5d88c77..6f27bf3 100644
--- a/src/libhydra/plugins/attr_sql/Makefile.in
+++ b/src/libhydra/plugins/attr_sql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-attr-sql.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-attr-sql.la
diff --git a/src/libhydra/plugins/kernel_klips/Makefile.am b/src/libhydra/plugins/kernel_klips/Makefile.am
deleted file mode 100644
index 1b98cab..0000000
--- a/src/libhydra/plugins/kernel_klips/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-AM_CPPFLAGS = \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra
-
-AM_CFLAGS = \
-	-rdynamic
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-kernel-klips.la
-else
-plugin_LTLIBRARIES = libstrongswan-kernel-klips.la
-endif
-
-libstrongswan_kernel_klips_la_SOURCES = \
-	kernel_klips_plugin.h kernel_klips_plugin.c \
-	kernel_klips_ipsec.h kernel_klips_ipsec.c pfkeyv2.h
-
-libstrongswan_kernel_klips_la_LDFLAGS = -module -avoid-version
diff --git a/src/libhydra/plugins/kernel_klips/Makefile.in b/src/libhydra/plugins/kernel_klips/Makefile.in
deleted file mode 100644
index f20ceb4..0000000
--- a/src/libhydra/plugins/kernel_klips/Makefile.in
+++ /dev/null
@@ -1,762 +0,0 @@
-# Makefile.in generated by automake 1.13.3 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_klips
-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_klips_la_LIBADD =
-am_libstrongswan_kernel_klips_la_OBJECTS = kernel_klips_plugin.lo \
-	kernel_klips_ipsec.lo
-libstrongswan_kernel_klips_la_OBJECTS =  \
-	$(am_libstrongswan_kernel_klips_la_OBJECTS)
-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_klips_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-	$(AM_CFLAGS) $(CFLAGS) \
-	$(libstrongswan_kernel_klips_la_LDFLAGS) $(LDFLAGS) -o $@
- at MONOLITHIC_FALSE@am_libstrongswan_kernel_klips_la_rpath = -rpath \
- at MONOLITHIC_FALSE@	$(plugindir)
- at MONOLITHIC_TRUE@am_libstrongswan_kernel_klips_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_klips_la_SOURCES)
-DIST_SOURCES = $(libstrongswan_kernel_klips_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@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-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@
-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@
-PTHREADLIB = @PTHREADLIB@
-PYTHON = @PYTHON@
-PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_VERSION = @PYTHON_VERSION@
-RANLIB = @RANLIB@
-RTLIB = @RTLIB@
-RUBY = @RUBY@
-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@
-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@
-libdir = @libdir@
-libexecdir = @libexecdir@
-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@
-sysconfdir = @sysconfdir@
-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
-
-AM_CFLAGS = \
-	-rdynamic
-
- at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-kernel-klips.la
- at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-kernel-klips.la
-libstrongswan_kernel_klips_la_SOURCES = \
-	kernel_klips_plugin.h kernel_klips_plugin.c \
-	kernel_klips_ipsec.h kernel_klips_ipsec.c pfkeyv2.h
-
-libstrongswan_kernel_klips_la_LDFLAGS = -module -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_klips/Makefile'; \
-	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/libhydra/plugins/kernel_klips/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-	@case '$?' in \
-	  *config.status*) \
-	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-	  *) \
-	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-	esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure:  $(am__configure_deps)
-	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
-	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(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-klips.la: $(libstrongswan_kernel_klips_la_OBJECTS) $(libstrongswan_kernel_klips_la_DEPENDENCIES) $(EXTRA_libstrongswan_kernel_klips_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(libstrongswan_kernel_klips_la_LINK) $(am_libstrongswan_kernel_klips_la_rpath) $(libstrongswan_kernel_klips_la_OBJECTS) $(libstrongswan_kernel_klips_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-	-rm -f *.$(OBJEXT)
-
-distclean-compile:
-	-rm -f *.tab.c
-
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_klips_ipsec.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/kernel_klips_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_klips/kernel_klips_ipsec.c b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
deleted file mode 100644
index a75ccf3..0000000
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.c
+++ /dev/null
@@ -1,2652 +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 <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <stdint.h>
-#include "pfkeyv2.h"
-#include <linux/udp.h>
-#include <net/if.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#include "kernel_klips_ipsec.h"
-
-#include <hydra.h>
-#include <utils/debug.h>
-#include <collections/linked_list.h>
-#include <threading/thread.h>
-#include <threading/mutex.h>
-#include <processing/jobs/callback_job.h>
-
-/** default timeout for generated SPIs (in seconds) */
-#define SPI_TIMEOUT 30
-
-/** buffer size for PF_KEY messages */
-#define PFKEY_BUFFER_SIZE 2048
-
-/** PF_KEY messages are 64 bit aligned */
-#define PFKEY_ALIGNMENT 8
-/** aligns len to 64 bits */
-#define PFKEY_ALIGN(len) (((len) + PFKEY_ALIGNMENT - 1) & ~(PFKEY_ALIGNMENT - 1))
-/** calculates the properly padded length in 64 bit chunks */
-#define PFKEY_LEN(len) ((PFKEY_ALIGN(len) / PFKEY_ALIGNMENT))
-/** calculates user mode length i.e. in bytes */
-#define PFKEY_USER_LEN(len) ((len) * PFKEY_ALIGNMENT)
-
-/** given a PF_KEY message header and an extension this updates the length in the header */
-#define PFKEY_EXT_ADD(msg, ext) ((msg)->sadb_msg_len += ((struct sadb_ext*)ext)->sadb_ext_len)
-/** given a PF_KEY message header this returns a pointer to the next extension */
-#define PFKEY_EXT_ADD_NEXT(msg) ((struct sadb_ext*)(((char*)(msg)) + PFKEY_USER_LEN((msg)->sadb_msg_len)))
-/** copy an extension and append it to a PF_KEY message */
-#define PFKEY_EXT_COPY(msg, ext) (PFKEY_EXT_ADD(msg, memcpy(PFKEY_EXT_ADD_NEXT(msg), ext, PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len))))
-/** given a PF_KEY extension this returns a pointer to the next extension */
-#define PFKEY_EXT_NEXT(ext) ((struct sadb_ext*)(((char*)(ext)) + PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len)))
-/** given a PF_KEY extension this returns a pointer to the next extension also updates len (len in 64 bit words) */
-#define PFKEY_EXT_NEXT_LEN(ext,len) ((len) -= (ext)->sadb_ext_len, PFKEY_EXT_NEXT(ext))
-/** true if ext has a valid length and len is large enough to contain ext (assuming len in 64 bit words) */
-#define PFKEY_EXT_OK(ext,len) ((len) >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
-				(ext)->sadb_ext_len >= PFKEY_LEN(sizeof(struct sadb_ext)) && \
-				(ext)->sadb_ext_len <= (len))
-
-/** special SPI values used for policies in KLIPS */
-#define SPI_PASS 256
-#define SPI_DROP 257
-#define SPI_REJECT 258
-#define SPI_HOLD 259
-#define SPI_TRAP 260
-#define SPI_TRAPSUBNET 261
-
-/** the prefix of the name of KLIPS ipsec devices */
-#define IPSEC_DEV_PREFIX "ipsec"
-/** this is the default number of ipsec devices */
-#define DEFAULT_IPSEC_DEV_COUNT 4
-/** TRUE if the given name matches an ipsec device */
-#define IS_IPSEC_DEV(name) (strpfx((name), IPSEC_DEV_PREFIX))
-
-/** the following stuff is from ipsec_tunnel.h */
-struct ipsectunnelconf
-{
-	__u32	cf_cmd;
-	union
-	{
-		char	cfu_name[12];
-	} cf_u;
-#define cf_name cf_u.cfu_name
-};
-
-#define IPSEC_SET_DEV (SIOCDEVPRIVATE)
-#define IPSEC_DEL_DEV (SIOCDEVPRIVATE + 1)
-#define IPSEC_CLR_DEV (SIOCDEVPRIVATE + 2)
-
-typedef struct private_kernel_klips_ipsec_t private_kernel_klips_ipsec_t;
-
-/**
- * Private variables and functions of kernel_klips class.
- */
-struct private_kernel_klips_ipsec_t
-{
-	/**
-	 * Public part of the kernel_klips_t object.
-	 */
-	kernel_klips_ipsec_t public;
-
-	/**
-	 * mutex to lock access to various lists
-	 */
-	mutex_t *mutex;
-
-	/**
-	 * List of installed policies (policy_entry_t)
-	 */
-	linked_list_t *policies;
-
-	/**
-	 * List of allocated SPIs without installed SA (sa_entry_t)
-	 */
-	linked_list_t *allocated_spis;
-
-	/**
-	 * List of installed SAs (sa_entry_t)
-	 */
-	linked_list_t *installed_sas;
-
-	/**
-	 * whether to install routes along policies
-	 */
-	bool install_routes;
-
-	/**
-	 * List of ipsec devices (ipsec_dev_t)
-	 */
-	linked_list_t *ipsec_devices;
-
-	/**
-	 * mutex to lock access to the PF_KEY socket
-	 */
-	mutex_t *mutex_pfkey;
-
-	/**
-	 * PF_KEY socket to communicate with the kernel
-	 */
-	int socket;
-
-	/**
-	 * PF_KEY socket to receive acquire and expire events
-	 */
-	int socket_events;
-
-	/**
-	 * sequence number for messages sent to the kernel
-	 */
-	int seq;
-
-};
-
-
-typedef struct ipsec_dev_t ipsec_dev_t;
-
-/**
- * ipsec device
- */
-struct ipsec_dev_t {
-	/** name of the virtual ipsec interface */
-	char name[IFNAMSIZ];
-
-	/** name of the physical interface */
-	char phys_name[IFNAMSIZ];
-
-	/** by how many CHILD_SA's this ipsec device is used */
-	u_int refcount;
-};
-
-/**
- * compare the given name with the virtual device name
- */
-static inline bool ipsec_dev_match_byname(ipsec_dev_t *current, char *name)
-{
-	return name && streq(current->name, name);
-}
-
-/**
- * compare the given name with the physical device name
- */
-static inline bool ipsec_dev_match_byphys(ipsec_dev_t *current, char *name)
-{
-	return name && streq(current->phys_name, name);
-}
-
-/**
- * matches free ipsec devices
- */
-static inline bool ipsec_dev_match_free(ipsec_dev_t *current)
-{
-	return current->refcount == 0;
-}
-
-/**
- * tries to find an ipsec_dev_t object by name
- */
-static status_t find_ipsec_dev(private_kernel_klips_ipsec_t *this, char *name,
-							   ipsec_dev_t **dev)
-{
-	linked_list_match_t match = (linked_list_match_t)(IS_IPSEC_DEV(name) ?
-								ipsec_dev_match_byname : ipsec_dev_match_byphys);
-	return this->ipsec_devices->find_first(this->ipsec_devices, match,
-												(void**)dev, name);
-}
-
-/**
- * attach an ipsec device to a physical interface
- */
-static status_t attach_ipsec_dev(char* name, char *phys_name)
-{
-	int sock;
-	struct ifreq req;
-	struct ipsectunnelconf *itc = (struct ipsectunnelconf*)&req.ifr_data;
-	short phys_flags;
-	int mtu;
-
-	DBG2(DBG_KNL, "attaching virtual interface %s to %s", name, phys_name);
-
-	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0)
-	{
-		return FAILED;
-	}
-
-	strncpy(req.ifr_name, phys_name, IFNAMSIZ);
-	if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
-	{
-		close(sock);
-		return FAILED;
-	}
-	phys_flags = req.ifr_flags;
-
-	strncpy(req.ifr_name, name, IFNAMSIZ);
-	if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
-	{
-		close(sock);
-		return FAILED;
-	}
-
-	if (req.ifr_flags & IFF_UP)
-	{
-		/* if it's already up, it is already attached, detach it first */
-		ioctl(sock, IPSEC_DEL_DEV, &req);
-	}
-
-	/* attach it */
-	strncpy(req.ifr_name, name, IFNAMSIZ);
-	strncpy(itc->cf_name, phys_name, sizeof(itc->cf_name));
-	ioctl(sock, IPSEC_SET_DEV, &req);
-
-	/* copy address from physical to virtual */
-	strncpy(req.ifr_name, phys_name, IFNAMSIZ);
-	if (ioctl(sock, SIOCGIFADDR, &req) == 0)
-	{
-		strncpy(req.ifr_name, name, IFNAMSIZ);
-		ioctl(sock, SIOCSIFADDR, &req);
-	}
-
-	/* copy net mask from physical to virtual */
-	strncpy(req.ifr_name, phys_name, IFNAMSIZ);
-	if (ioctl(sock, SIOCGIFNETMASK, &req) == 0)
-	{
-		strncpy(req.ifr_name, name, IFNAMSIZ);
-		ioctl(sock, SIOCSIFNETMASK, &req);
-	}
-
-	/* copy other flags and addresses */
-	strncpy(req.ifr_name, name, IFNAMSIZ);
-	if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
-	{
-		if (phys_flags & IFF_POINTOPOINT)
-		{
-			req.ifr_flags |= IFF_POINTOPOINT;
-			req.ifr_flags &= ~IFF_BROADCAST;
-			ioctl(sock, SIOCSIFFLAGS, &req);
-
-			strncpy(req.ifr_name, phys_name, IFNAMSIZ);
-			if (ioctl(sock, SIOCGIFDSTADDR, &req) == 0)
-			{
-				strncpy(req.ifr_name, name, IFNAMSIZ);
-				ioctl(sock, SIOCSIFDSTADDR, &req);
-			}
-		}
-		else if (phys_flags & IFF_BROADCAST)
-		{
-			req.ifr_flags &= ~IFF_POINTOPOINT;
-			req.ifr_flags |= IFF_BROADCAST;
-			ioctl(sock, SIOCSIFFLAGS, &req);
-
-			strncpy(req.ifr_name, phys_name, IFNAMSIZ);
-			if (ioctl(sock, SIOCGIFBRDADDR, &req)==0)
-			{
-				strncpy(req.ifr_name, name, IFNAMSIZ);
-				ioctl(sock, SIOCSIFBRDADDR, &req);
-			}
-		}
-		else
-		{
-			req.ifr_flags &= ~IFF_POINTOPOINT;
-			req.ifr_flags &= ~IFF_BROADCAST;
-			ioctl(sock, SIOCSIFFLAGS, &req);
-		}
-	}
-
-	mtu = lib->settings->get_int(lib->settings,
-								 "%s.plugins.kernel-klips.ipsec_dev_mtu", 0,
-								 lib->ns);
-	if (mtu <= 0)
-	{
-		/* guess MTU as physical MTU - ESP overhead [- NAT-T overhead]
-		 * ESP overhead      : 73 bytes
-		 * NAT-T overhead    :  8 bytes ==> 81 bytes
-		 *
-		 * assuming tunnel mode with AES encryption and integrity
-		 * outer IP header  : 20 bytes
-		 * (NAT-T UDP header:  8 bytes)
-		 * ESP header       :  8 bytes
-		 * IV               : 16 bytes
-		 * padding          : 15 bytes (worst-case)
-		 * pad len / NH     :  2 bytes
-		 * auth data        : 12 bytes
-		 */
-		strncpy(req.ifr_name, phys_name, IFNAMSIZ);
-		ioctl(sock, SIOCGIFMTU, &req);
-		mtu = req.ifr_mtu - 81;
-	}
-
-	/* set MTU */
-	strncpy(req.ifr_name, name, IFNAMSIZ);
-	req.ifr_mtu = mtu;
-	ioctl(sock, SIOCSIFMTU, &req);
-
-	/* bring ipsec device UP */
-	if (ioctl(sock, SIOCGIFFLAGS, &req) == 0)
-	{
-		req.ifr_flags |= IFF_UP;
-		ioctl(sock, SIOCSIFFLAGS, &req);
-	}
-
-	close(sock);
-	return SUCCESS;
-}
-
-/**
- * detach an ipsec device from a physical interface
- */
-static status_t detach_ipsec_dev(char* name, char *phys_name)
-{
-	int sock;
-	struct ifreq req;
-
-	DBG2(DBG_KNL, "detaching virtual interface %s from %s", name,
-			strlen(phys_name) ? phys_name : "any physical interface");
-
-	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0)
-	{
-		return FAILED;
-	}
-
-	strncpy(req.ifr_name, name, IFNAMSIZ);
-	if (ioctl(sock, SIOCGIFFLAGS, &req) < 0)
-	{
-		close(sock);
-		return FAILED;
-	}
-
-	/* shutting interface down */
-	if (req.ifr_flags & IFF_UP)
-	{
-		req.ifr_flags &= ~IFF_UP;
-		ioctl(sock, SIOCSIFFLAGS, &req);
-	}
-
-	/* unset address */
-	memset(&req.ifr_addr, 0, sizeof(req.ifr_addr));
-	req.ifr_addr.sa_family = AF_INET;
-	ioctl(sock, SIOCSIFADDR, &req);
-
-	/* detach interface */
-	ioctl(sock, IPSEC_DEL_DEV, &req);
-
-	close(sock);
-	return SUCCESS;
-}
-
-/**
- * destroy an ipsec_dev_t object
- */
-static void ipsec_dev_destroy(ipsec_dev_t *this)
-{
-	detach_ipsec_dev(this->name, this->phys_name);
-	free(this);
-}
-
-
-typedef struct route_entry_t route_entry_t;
-
-/**
- * installed routing entry
- */
-struct route_entry_t {
-	/** Name of the interface the route is bound to */
-	char *if_name;
-
-	/** Source ip of the route */
-	host_t *src_ip;
-
-	/** Gateway for this route */
-	host_t *gateway;
-
-	/** Destination net */
-	chunk_t dst_net;
-
-	/** Destination net prefixlen */
-	u_int8_t prefixlen;
-};
-
-/**
- * destroy an route_entry_t object
- */
-static void route_entry_destroy(route_entry_t *this)
-{
-	free(this->if_name);
-	this->src_ip->destroy(this->src_ip);
-	this->gateway->destroy(this->gateway);
-	chunk_free(&this->dst_net);
-	free(this);
-}
-
-typedef struct policy_entry_t policy_entry_t;
-
-/**
- * installed kernel policy.
- */
-struct policy_entry_t {
-
-	/** reqid of this policy, if setup as trap */
-	u_int32_t reqid;
-
-	/** direction of this policy: in, out, forward */
-	u_int8_t direction;
-
-	/** parameters of installed policy */
-	struct {
-		/** subnet and port */
-		host_t *net;
-		/** subnet mask */
-		u_int8_t mask;
-		/** protocol */
-		u_int8_t proto;
-	} src, dst;
-
-	/** associated route installed for this policy */
-	route_entry_t *route;
-
-	/** by how many CHILD_SA's this policy is actively used */
-	u_int activecount;
-
-	/** by how many CHILD_SA's this policy is trapped */
-	u_int trapcount;
-};
-
-/**
- * convert a numerical netmask to a host_t
- */
-static host_t *mask2host(int family, u_int8_t mask)
-{
-	static const u_char bitmask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
-	chunk_t chunk = chunk_alloca(family == AF_INET ? 4 : 16);
-	int bytes = mask / 8, bits = mask % 8;
-	memset(chunk.ptr, 0xFF, bytes);
-	memset(chunk.ptr + bytes, 0, chunk.len - bytes);
-	if (bits)
-	{
-		chunk.ptr[bytes] =  bitmask[bits];
-	}
-	return host_create_from_chunk(family, chunk, 0);
-}
-
-/**
- * check if a host is in a subnet (host with netmask in bits)
- */
-static bool is_host_in_net(host_t *host, host_t *net, u_int8_t mask)
-{
-	static const u_char bitmask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
-	chunk_t host_chunk, net_chunk;
-	int bytes = mask / 8, bits = mask % 8;
-
-	host_chunk = host->get_address(host);
-	net_chunk = net->get_address(net);
-
-	if (host_chunk.len != net_chunk.len)
-	{
-		return FALSE;
-	}
-
-	if (memeq(host_chunk.ptr, net_chunk.ptr, bytes))
-	{
-		return (bits == 0) ||
-			   (host_chunk.ptr[bytes] & bitmask[bits]) ==
-				   (net_chunk.ptr[bytes] & bitmask[bits]);
-	}
-
-	return FALSE;
-}
-
-/**
- * create a policy_entry_t object
- */
-static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts,
-		traffic_selector_t *dst_ts, policy_dir_t dir)
-{
-	policy_entry_t *policy = malloc_thing(policy_entry_t);
-	policy->reqid = 0;
-	policy->direction = dir;
-	policy->route = NULL;
-	policy->activecount = 0;
-	policy->trapcount = 0;
-
-	src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask);
-	dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask);
-
-	/* src or dest proto may be "any" (0), use more restrictive one */
-	policy->src.proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
-	policy->src.proto = policy->src.proto ? policy->src.proto : 0;
-	policy->dst.proto = policy->src.proto;
-
-	return policy;
-}
-
-/**
- * destroy a policy_entry_t object
- */
-static void policy_entry_destroy(policy_entry_t *this)
-{
-	DESTROY_IF(this->src.net);
-	DESTROY_IF(this->dst.net);
-	if (this->route)
-	{
-		route_entry_destroy(this->route);
-	}
-	free(this);
-}
-
-/**
- * compares two policy_entry_t
- */
-static inline bool policy_entry_equals(policy_entry_t *current, policy_entry_t *policy)
-{
-	return current->direction == policy->direction &&
-		   current->src.proto == policy->src.proto &&
-		   current->dst.proto == policy->dst.proto &&
-		   current->src.mask == policy->src.mask &&
-		   current->dst.mask == policy->dst.mask &&
-		   current->src.net->equals(current->src.net, policy->src.net) &&
-		   current->dst.net->equals(current->dst.net, policy->dst.net);
-}
-
-static inline bool policy_entry_match_byaddrs(policy_entry_t *current, host_t *src,
-		host_t *dst)
-{
-	return is_host_in_net(src, current->src.net, current->src.mask) &&
-			is_host_in_net(dst, current->dst.net, current->dst.mask);
-}
-
-typedef struct sa_entry_t sa_entry_t;
-
-/**
- * used for two things:
- * - allocated SPIs that have not yet resulted in an installed SA
- * - installed inbound SAs with enabled UDP encapsulation
- */
-struct sa_entry_t {
-
-	/** protocol of this SA */
-	u_int8_t protocol;
-
-	/** reqid of this SA */
-	u_int32_t reqid;
-
-	/** SPI of this SA */
-	u_int32_t spi;
-
-	/** src address of this SA */
-	host_t *src;
-
-	/** dst address of this SA */
-	host_t *dst;
-
-	/** TRUE if this SA uses UDP encapsulation */
-	bool encap;
-
-	/** TRUE if this SA is inbound */
-	bool inbound;
-};
-
-/**
- * create an sa_entry_t object
- */
-static sa_entry_t *create_sa_entry(u_int8_t protocol, u_int32_t spi,
-								   u_int32_t reqid, host_t *src, host_t *dst,
-								   bool encap, bool inbound)
-{
-	sa_entry_t *sa = malloc_thing(sa_entry_t);
-	sa->protocol = protocol;
-	sa->reqid = reqid;
-	sa->spi = spi;
-	sa->src = src ? src->clone(src) : NULL;
-	sa->dst = dst ? dst->clone(dst) : NULL;
-	sa->encap = encap;
-	sa->inbound = inbound;
-	return sa;
-}
-
-/**
- * destroy an sa_entry_t object
- */
-static void sa_entry_destroy(sa_entry_t *this)
-{
-	DESTROY_IF(this->src);
-	DESTROY_IF(this->dst);
-	free(this);
-}
-
-/**
- * match an sa_entry_t for an inbound SA that uses UDP encapsulation by spi and src (remote) address
- */
-static inline bool sa_entry_match_encapbysrc(sa_entry_t *current, u_int32_t *spi,
-		host_t *src)
-{
-	return current->encap && current->inbound &&
-		   current->spi == *spi && src->ip_equals(src, current->src);
-}
-
-/**
- * match an sa_entry_t by protocol, spi and dst address (as the kernel does it)
- */
-static inline bool sa_entry_match_bydst(sa_entry_t *current, u_int8_t *protocol,
-		u_int32_t *spi, host_t *dst)
-{
-	return current->protocol == *protocol && current->spi == *spi && dst->ip_equals(dst, current->dst);
-}
-
-/**
- * match an sa_entry_t by protocol, reqid and spi
- */
-static inline bool sa_entry_match_byid(sa_entry_t *current, u_int8_t *protocol,
-		u_int32_t *spi, u_int32_t *reqid)
-{
-	return current->protocol == *protocol && current->spi == *spi && current->reqid == *reqid;
-}
-
-typedef struct pfkey_msg_t pfkey_msg_t;
-
-struct pfkey_msg_t
-{
-	/**
-	 * PF_KEY message base
-	 */
-	struct sadb_msg *msg;
-
-
-	/**
-	 * PF_KEY message extensions
-	 */
-	union {
-		struct sadb_ext *ext[SADB_EXT_MAX + 1];
-		struct {
-			struct sadb_ext *reserved;				/* SADB_EXT_RESERVED */
-			struct sadb_sa *sa;						/* SADB_EXT_SA */
-			struct sadb_lifetime *lft_current;		/* SADB_EXT_LIFETIME_CURRENT */
-			struct sadb_lifetime *lft_hard;			/* SADB_EXT_LIFETIME_HARD */
-			struct sadb_lifetime *lft_soft;			/* SADB_EXT_LIFETIME_SOFT */
-			struct sadb_address *src;				/* SADB_EXT_ADDRESS_SRC */
-			struct sadb_address *dst;				/* SADB_EXT_ADDRESS_DST */
-			struct sadb_address *proxy;				/* SADB_EXT_ADDRESS_PROXY */
-			struct sadb_key *key_auth;				/* SADB_EXT_KEY_AUTH */
-			struct sadb_key *key_encr;				/* SADB_EXT_KEY_ENCRYPT */
-			struct sadb_ident *id_src;				/* SADB_EXT_IDENTITY_SRC */
-			struct sadb_ident *id_dst;				/* SADB_EXT_IDENTITY_DST */
-			struct sadb_sens *sensitivity;			/* SADB_EXT_SENSITIVITY */
-			struct sadb_prop *proposal;				/* SADB_EXT_PROPOSAL */
-			struct sadb_supported *supported_auth;	/* SADB_EXT_SUPPORTED_AUTH */
-			struct sadb_supported *supported_encr;	/* SADB_EXT_SUPPORTED_ENCRYPT */
-			struct sadb_spirange *spirange;			/* SADB_EXT_SPIRANGE */
-			struct sadb_x_kmprivate *x_kmprivate;	/* SADB_X_EXT_KMPRIVATE */
-			struct sadb_ext *x_policy;				/* SADB_X_EXT_SATYPE2 */
-			struct sadb_ext *x_sa2;					/* SADB_X_EXT_SA2 */
-			struct sadb_address *x_dst2;			/* SADB_X_EXT_ADDRESS_DST2 */
-			struct sadb_address *x_src_flow;		/* SADB_X_EXT_ADDRESS_SRC_FLOW */
-			struct sadb_address *x_dst_flow;		/* SADB_X_EXT_ADDRESS_DST_FLOW */
-			struct sadb_address *x_src_mask;		/* SADB_X_EXT_ADDRESS_SRC_MASK */
-			struct sadb_address *x_dst_mask;		/* SADB_X_EXT_ADDRESS_DST_MASK */
-			struct sadb_x_debug *x_debug;			/* SADB_X_EXT_DEBUG */
-			struct sadb_protocol *x_protocol;		/* SADB_X_EXT_PROTOCOL */
-			struct sadb_x_nat_t_type *x_natt_type;	/* SADB_X_EXT_NAT_T_TYPE */
-			struct sadb_x_nat_t_port *x_natt_sport;	/* SADB_X_EXT_NAT_T_SPORT */
-			struct sadb_x_nat_t_port *x_natt_dport;	/* SADB_X_EXT_NAT_T_DPORT */
-			struct sadb_address *x_natt_oa;			/* SADB_X_EXT_NAT_T_OA */
-		} __attribute__((__packed__));
-	};
-};
-
-/**
- * convert a 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_COMP;
-		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_COMP:
-			return IPPROTO_COMP;
-		default:
-			return satype;
-	}
-}
-
-typedef struct kernel_algorithm_t kernel_algorithm_t;
-
-/**
- * Mapping of IKEv2 algorithms to PF_KEY algorithms
- */
-struct kernel_algorithm_t {
-	/**
-	 * Identifier specified in IKEv2
-	 */
-	int ikev2;
-
-	/**
-	 * Identifier as defined in pfkeyv2.h
-	 */
-	int kernel;
-};
-
-#define END_OF_LIST -1
-
-/**
- * Algorithms for encryption
- */
-static kernel_algorithm_t encryption_algs[] = {
-/*	{ENCR_DES_IV64,				0							}, */
-	{ENCR_DES,					SADB_EALG_DESCBC			},
-	{ENCR_3DES,					SADB_EALG_3DESCBC			},
-/*	{ENCR_RC5,					0							}, */
-/*	{ENCR_IDEA,					0							}, */
-/*	{ENCR_CAST,					0							}, */
-	{ENCR_BLOWFISH,				SADB_EALG_BFCBC				},
-/*	{ENCR_3IDEA,				0							}, */
-/*	{ENCR_DES_IV32,				0							}, */
-	{ENCR_NULL,					SADB_EALG_NULL				},
-	{ENCR_AES_CBC,				SADB_EALG_AESCBC			},
-/*	{ENCR_AES_CTR,				0							}, */
-/*	{ENCR_AES_CCM_ICV8,			0							}, */
-/*	{ENCR_AES_CCM_ICV12,		0							}, */
-/*	{ENCR_AES_CCM_ICV16,		0							}, */
-/*	{ENCR_AES_GCM_ICV8,			0							}, */
-/*	{ENCR_AES_GCM_ICV12,		0							}, */
-/*	{ENCR_AES_GCM_ICV16,		0							}, */
-	{END_OF_LIST,				0							},
-};
-
-/**
- * Algorithms for integrity protection
- */
-static kernel_algorithm_t integrity_algs[] = {
-	{AUTH_HMAC_MD5_96,			SADB_AALG_MD5HMAC			},
-	{AUTH_HMAC_SHA1_96,			SADB_AALG_SHA1HMAC			},
-	{AUTH_HMAC_SHA2_256_128,	SADB_AALG_SHA256_HMAC		},
-	{AUTH_HMAC_SHA2_384_192,	SADB_AALG_SHA384_HMAC		},
-	{AUTH_HMAC_SHA2_512_256,	SADB_AALG_SHA512_HMAC		},
-/*	{AUTH_DES_MAC,				0,							}, */
-/*	{AUTH_KPDK_MD5,				0,							}, */
-/*	{AUTH_AES_XCBC_96,			0,							}, */
-	{END_OF_LIST,				0,							},
-};
-
-#if 0
-/**
- * Algorithms for IPComp, unused yet
- */
-static kernel_algorithm_t compression_algs[] = {
-/*	{IPCOMP_OUI,				0							}, */
-	{IPCOMP_DEFLATE,			SADB_X_CALG_DEFLATE			},
-	{IPCOMP_LZS,				SADB_X_CALG_LZS				},
-/*	{IPCOMP_LZJH,				0							}, */
-	{END_OF_LIST,				0							},
-};
-#endif
-
-/**
- * Look up a kernel algorithm ID and its key size
- */
-static int lookup_algorithm(transform_type_t type, int ikev2)
-{
-	kernel_algorithm_t *list;
-	int alg = 0;
-
-	switch (type)
-	{
-		case ENCRYPTION_ALGORITHM:
-			list = encryption_algs;
-			break;
-		case INTEGRITY_ALGORITHM:
-			list = integrity_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;
-}
-
-/**
- * add a host behind a sadb_address extension
- */
-static void host2ext(host_t *host, struct sadb_address *ext)
-{
-	sockaddr_t *host_addr = host->get_sockaddr(host);
-	socklen_t *len = host->get_sockaddr_len(host);
-	memcpy((char*)(ext + 1), host_addr, *len);
-	ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + *len);
-}
-
-/**
- * add a host to the given sadb_msg
- */
-static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type)
-{
-	struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
-	addr->sadb_address_exttype = type;
-	host2ext(host, addr);
-	PFKEY_EXT_ADD(msg, addr);
-}
-
-/**
- * adds an empty address extension to the given sadb_msg
- */
-static void add_anyaddr_ext(struct sadb_msg *msg, int family, u_int8_t type)
-{
-	socklen_t len = (family == AF_INET) ? sizeof(struct sockaddr_in) :
-										  sizeof(struct sockaddr_in6);
-	struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg);
-	addr->sadb_address_exttype = type;
-	sockaddr_t *saddr = (sockaddr_t*)(addr + 1);
-	saddr->sa_family = family;
-	addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
-	PFKEY_EXT_ADD(msg, addr);
-}
-
-/**
- * add udp encap extensions to a sadb_msg
- */
-static void add_encap_ext(struct sadb_msg *msg, host_t *src, host_t *dst,
-							bool ports_only)
-{
-	struct sadb_x_nat_t_type* nat_type;
-	struct sadb_x_nat_t_port* nat_port;
-
-	if (!ports_only)
-	{
-		nat_type = (struct sadb_x_nat_t_type*)PFKEY_EXT_ADD_NEXT(msg);
-		nat_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
-		nat_type->sadb_x_nat_t_type_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_type));
-		nat_type->sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP;
-		PFKEY_EXT_ADD(msg, nat_type);
-	}
-
-	nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
-	nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
-	nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
-	nat_port->sadb_x_nat_t_port_port = src->get_port(src);
-	PFKEY_EXT_ADD(msg, nat_port);
-
-	nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg);
-	nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
-	nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port));
-	nat_port->sadb_x_nat_t_port_port = dst->get_port(dst);
-	PFKEY_EXT_ADD(msg, nat_port);
-}
-
-/**
- * build an SADB_X_ADDFLOW msg
- */
-static void build_addflow(struct sadb_msg *msg, u_int8_t satype, u_int32_t spi,
-		host_t *src, host_t *dst, host_t *src_net, u_int8_t src_mask,
-		host_t *dst_net, u_int8_t dst_mask, u_int8_t protocol, bool replace)
-{
-	struct sadb_sa *sa;
-	struct sadb_protocol *proto;
-	host_t *host;
-
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_X_ADDFLOW;
-	msg->sadb_msg_satype = satype;
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
-	sa->sadb_sa_exttype = SADB_EXT_SA;
-	sa->sadb_sa_spi = spi;
-	sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
-	sa->sadb_sa_flags = replace ? SADB_X_SAFLAGS_REPLACEFLOW : 0;
-	PFKEY_EXT_ADD(msg, sa);
-
-	if (!src)
-	{
-		add_anyaddr_ext(msg, src_net->get_family(src_net), SADB_EXT_ADDRESS_SRC);
-	}
-	else
-	{
-		add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
-	}
-
-	if (!dst)
-	{
-		add_anyaddr_ext(msg, dst_net->get_family(dst_net), SADB_EXT_ADDRESS_DST);
-	}
-	else
-	{
-		add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
-	}
-
-	add_addr_ext(msg, src_net, SADB_X_EXT_ADDRESS_SRC_FLOW);
-	add_addr_ext(msg, dst_net, SADB_X_EXT_ADDRESS_DST_FLOW);
-
-	host = mask2host(src_net->get_family(src_net), src_mask);
-	add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_SRC_MASK);
-	host->destroy(host);
-
-	host = mask2host(dst_net->get_family(dst_net), dst_mask);
-	add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_DST_MASK);
-	host->destroy(host);
-
-	proto = (struct sadb_protocol*)PFKEY_EXT_ADD_NEXT(msg);
-	proto->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
-	proto->sadb_protocol_len = PFKEY_LEN(sizeof(struct sadb_protocol));
-	proto->sadb_protocol_proto = protocol;
-	PFKEY_EXT_ADD(msg, proto);
-}
-
-/**
- * build an SADB_X_DELFLOW msg
- */
-static void build_delflow(struct sadb_msg *msg, u_int8_t satype,
-		host_t *src_net, u_int8_t src_mask, host_t *dst_net, u_int8_t dst_mask,
-		u_int8_t protocol)
-{
-	struct sadb_protocol *proto;
-	host_t *host;
-
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_X_DELFLOW;
-	msg->sadb_msg_satype = satype;
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	add_addr_ext(msg, src_net, SADB_X_EXT_ADDRESS_SRC_FLOW);
-	add_addr_ext(msg, dst_net, SADB_X_EXT_ADDRESS_DST_FLOW);
-
-	host = mask2host(src_net->get_family(src_net),
-					 src_mask);
-	add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_SRC_MASK);
-	host->destroy(host);
-
-	host = mask2host(dst_net->get_family(dst_net),
-					 dst_mask);
-	add_addr_ext(msg, host, SADB_X_EXT_ADDRESS_DST_MASK);
-	host->destroy(host);
-
-	proto = (struct sadb_protocol*)PFKEY_EXT_ADD_NEXT(msg);
-	proto->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
-	proto->sadb_protocol_len = PFKEY_LEN(sizeof(struct sadb_protocol));
-	proto->sadb_protocol_proto = protocol;
-	PFKEY_EXT_ADD(msg, proto);
-}
-
-/**
- * Parses a pfkey message received from the kernel
- */
-static status_t parse_pfkey_message(struct sadb_msg *msg, pfkey_msg_t *out)
-{
-	struct sadb_ext* ext;
-	size_t len;
-
-	memset(out, 0, sizeof(pfkey_msg_t));
-	out->msg = msg;
-
-	len = msg->sadb_msg_len;
-	len -= PFKEY_LEN(sizeof(struct sadb_msg));
-
-	ext = (struct sadb_ext*)(((char*)msg) + sizeof(struct sadb_msg));
-
-	while (len >= PFKEY_LEN(sizeof(struct sadb_ext)))
-	{
-		if (ext->sadb_ext_len < PFKEY_LEN(sizeof(struct sadb_ext)) ||
-			ext->sadb_ext_len > len)
-		{
-			DBG1(DBG_KNL, "length of PF_KEY extension (%d) is invalid", ext->sadb_ext_type);
-			break;
-		}
-
-		if ((ext->sadb_ext_type > SADB_EXT_MAX) || (!ext->sadb_ext_type))
-		{
-			DBG1(DBG_KNL, "type of PF_KEY extension (%d) is invalid", ext->sadb_ext_type);
-			break;
-		}
-
-		if (out->ext[ext->sadb_ext_type])
-		{
-			DBG1(DBG_KNL, "duplicate PF_KEY extension of type (%d)", ext->sadb_ext_type);
-			break;
-		}
-
-		out->ext[ext->sadb_ext_type] = ext;
-		ext = PFKEY_EXT_NEXT_LEN(ext, len);
-	}
-
-	if (len)
-	{
-		DBG1(DBG_KNL, "PF_KEY message length is invalid");
-		return FAILED;
-	}
-
-	return SUCCESS;
-}
-
-/**
- * Send a message to a specific PF_KEY socket and handle the response.
- */
-static status_t pfkey_send_socket(private_kernel_klips_ipsec_t *this, int socket,
-					struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
-{
-	unsigned char buf[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg;
-	int in_len, len;
-
-	this->mutex_pfkey->lock(this->mutex_pfkey);
-
-	in->sadb_msg_seq = ++this->seq;
-	in->sadb_msg_pid = getpid();
-
-	in_len = PFKEY_USER_LEN(in->sadb_msg_len);
-
-	while (TRUE)
-	{
-		len = send(socket, in, in_len, 0);
-
-		if (len != in_len)
-		{
-			switch (errno)
-			{
-				case EINTR:
-					/* interrupted, try again */
-					continue;
-				case EINVAL:
-				case EEXIST:
-				case ESRCH:
-					/* we should also get a response for these from KLIPS */
-					break;
-				default:
-					this->mutex_pfkey->unlock(this->mutex_pfkey);
-					DBG1(DBG_KNL, "error sending to PF_KEY socket: %s (%d)",
-							strerror(errno), errno);
-					return FAILED;
-			}
-		}
-		break;
-	}
-
-	while (TRUE)
-	{
-		msg = (struct sadb_msg*)buf;
-
-		len = recv(socket, buf, sizeof(buf), 0);
-
-		if (len < 0)
-		{
-			if (errno == EINTR)
-			{
-				DBG1(DBG_KNL, "got interrupted");
-				/* interrupted, try again */
-				continue;
-			}
-			this->mutex_pfkey->unlock(this->mutex_pfkey);
-			DBG1(DBG_KNL, "error reading from PF_KEY socket: %s", strerror(errno));
-			return FAILED;
-		}
-		if (len < sizeof(struct sadb_msg) ||
-			msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg)))
-		{
-			this->mutex_pfkey->unlock(this->mutex_pfkey);
-			DBG1(DBG_KNL, "received corrupted PF_KEY message");
-			return FAILED;
-		}
-		if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
-		{
-			this->mutex_pfkey->unlock(this->mutex_pfkey);
-			DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message");
-			return FAILED;
-		}
-		if (msg->sadb_msg_pid != in->sadb_msg_pid)
-		{
-			DBG2(DBG_KNL, "received PF_KEY message is not intended for us");
-			continue;
-		}
-		if (msg->sadb_msg_seq != this->seq)
-		{
-			DBG1(DBG_KNL, "received PF_KEY message with invalid sequence number,"
-					" was %d expected %d", msg->sadb_msg_seq, this->seq);
-			if (msg->sadb_msg_seq < this->seq)
-			{
-				continue;
-			}
-			this->mutex_pfkey->unlock(this->mutex_pfkey);
-			return FAILED;
-		}
-		if (msg->sadb_msg_type != in->sadb_msg_type)
-		{
-			DBG2(DBG_KNL, "received PF_KEY message of wrong type,"
-					" was %d expected %d, ignoring",
-					msg->sadb_msg_type, in->sadb_msg_type);
-		}
-		break;
-	}
-
-	*out_len = len;
-	*out = (struct sadb_msg*)malloc(len);
-	memcpy(*out, buf, len);
-
-	this->mutex_pfkey->unlock(this->mutex_pfkey);
-
-	return SUCCESS;
-}
-
-/**
- * Send a message to the default PF_KEY socket.
- */
-static status_t pfkey_send(private_kernel_klips_ipsec_t *this,
-					struct sadb_msg *in, struct sadb_msg **out, size_t *out_len)
-{
-	return pfkey_send_socket(this, this->socket, in, out, out_len);
-}
-
-/**
- * Send a message to the default PF_KEY socket and handle the response.
- */
-static status_t pfkey_send_ack(private_kernel_klips_ipsec_t *this, struct sadb_msg *in)
-{
-	struct sadb_msg *out;
-	size_t len;
-
-	if (pfkey_send(this, in, &out, &len) != SUCCESS)
-	{
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "PF_KEY error: %s (%d)",
-					   strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-	free(out);
-	return SUCCESS;
-}
-
-/**
- * Add an eroute to KLIPS
- */
-static status_t add_eroute(private_kernel_klips_ipsec_t *this, u_int8_t satype,
-		u_int32_t spi, host_t *src, host_t *dst, host_t *src_net, u_int8_t src_mask,
-		host_t *dst_net, u_int8_t dst_mask, u_int8_t protocol, bool replace)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg = (struct sadb_msg*)request;
-
-	memset(&request, 0, sizeof(request));
-
-	build_addflow(msg, satype, spi, src, dst, src_net, src_mask,
-			dst_net, dst_mask, protocol, replace);
-
-	return pfkey_send_ack(this, msg);
-}
-
-/**
- * Delete an eroute fom KLIPS
- */
-static status_t del_eroute(private_kernel_klips_ipsec_t *this, u_int8_t satype,
-		host_t *src_net, u_int8_t src_mask, host_t *dst_net, u_int8_t dst_mask,
-		u_int8_t protocol)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg = (struct sadb_msg*)request;
-
-	memset(&request, 0, sizeof(request));
-
-	build_delflow(msg, satype, src_net, src_mask, dst_net, dst_mask, protocol);
-
-	return pfkey_send_ack(this, msg);
-}
-
-/**
- * Process a SADB_ACQUIRE message from the kernel
- */
-static void process_acquire(private_kernel_klips_ipsec_t *this, struct sadb_msg* msg)
-{
-	pfkey_msg_t response;
-	host_t *src, *dst;
-	u_int32_t reqid;
-	u_int8_t proto;
-	policy_entry_t *policy;
-
-	switch (msg->sadb_msg_satype)
-	{
-		case SADB_SATYPE_UNSPEC:
-		case SADB_SATYPE_ESP:
-		case SADB_SATYPE_AH:
-			break;
-		default:
-			/* acquire for AH/ESP only */
-			return;
-	}
-
-	if (parse_pfkey_message(msg, &response) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "parsing SADB_ACQUIRE from kernel failed");
-		return;
-	}
-
-	/* KLIPS provides us only with the source and destination address,
-	 * and the transport protocol of the packet that triggered the policy.
-	 * we use this information to find a matching policy in our cache.
-	 * because KLIPS installs a narrow %hold eroute covering only this information,
-	 * we replace both the %trap and this %hold eroutes with a broader %hold
-	 * eroute covering the whole policy */
-	src = host_create_from_sockaddr((sockaddr_t*)(response.src + 1));
-	dst = host_create_from_sockaddr((sockaddr_t*)(response.dst + 1));
-	proto = response.src->sadb_address_proto;
-	if (!src || !dst || src->get_family(src) != dst->get_family(dst))
-	{
-		DBG1(DBG_KNL, "received an SADB_ACQUIRE with invalid hosts");
-		return;
-	}
-
-	DBG2(DBG_KNL, "received an SADB_ACQUIRE for %H == %H : %d", src, dst, proto);
-	this->mutex->lock(this->mutex);
-	if (this->policies->find_first(this->policies,
-			(linked_list_match_t)policy_entry_match_byaddrs,
-				(void**)&policy, src, dst) != SUCCESS)
-	{
-		this->mutex->unlock(this->mutex);
-		DBG1(DBG_KNL, "received an SADB_ACQUIRE, but found no matching policy");
-		return;
-	}
-	if ((reqid = policy->reqid) == 0)
-	{
-		this->mutex->unlock(this->mutex);
-		DBG1(DBG_KNL, "received an SADB_ACQUIRE, but policy is not routed anymore");
-		return;
-	}
-
-	/* add a broad %hold eroute that replaces the %trap eroute */
-	add_eroute(this, SADB_X_SATYPE_INT, htonl(SPI_HOLD), NULL, NULL,
-			policy->src.net, policy->src.mask, policy->dst.net, policy->dst.mask,
-			policy->src.proto, TRUE);
-
-	/* remove the narrow %hold eroute installed by KLIPS */
-	del_eroute(this, SADB_X_SATYPE_INT, src, 32, dst, 32, proto);
-
-	this->mutex->unlock(this->mutex);
-
-	hydra->kernel_interface->acquire(hydra->kernel_interface, reqid, NULL,
-									 NULL);
-}
-
-/**
- * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel
- */
-static void process_mapping(private_kernel_klips_ipsec_t *this, struct sadb_msg* msg)
-{
-	pfkey_msg_t response;
-	u_int32_t spi, reqid;
-	host_t *old_src, *new_src;
-
-	DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING");
-
-	if (parse_pfkey_message(msg, &response) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "parsing SADB_X_NAT_T_NEW_MAPPING from kernel failed");
-		return;
-	}
-
-	spi = response.sa->sadb_sa_spi;
-
-	if (satype2proto(msg->sadb_msg_satype) == IPPROTO_ESP)
-	{
-		sa_entry_t *sa;
-		sockaddr_t *addr = (sockaddr_t*)(response.src + 1);
-		old_src = host_create_from_sockaddr(addr);
-
-		this->mutex->lock(this->mutex);
-		if (!old_src || this->installed_sas->find_first(this->installed_sas,
-				(linked_list_match_t)sa_entry_match_encapbysrc,
-					(void**)&sa, &spi, old_src) != SUCCESS)
-		{
-			this->mutex->unlock(this->mutex);
-			DBG1(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING, but found no matching SA");
-			return;
-		}
-		reqid = sa->reqid;
-		this->mutex->unlock(this->mutex);
-
-		addr = (sockaddr_t*)(response.dst + 1);
-		switch (addr->sa_family)
-		{
-			case AF_INET:
-			{
-				struct sockaddr_in *sin = (struct sockaddr_in*)addr;
-				sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
-			}
-			case AF_INET6:
-			{
-				struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
-				sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port);
-			}
-			default:
-				break;
-		}
-		new_src = host_create_from_sockaddr(addr);
-		if (new_src)
-		{
-			hydra->kernel_interface->mapping(hydra->kernel_interface, reqid,
-											 spi, new_src);
-		}
-	}
-}
-
-/**
- * Receives events from kernel
- */
-static job_requeue_t receive_events(private_kernel_klips_ipsec_t *this)
-{
-	unsigned char buf[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg = (struct sadb_msg*)buf;
-	int len;
-	bool oldstate;
-
-	oldstate = thread_cancelability(TRUE);
-	len = recv(this->socket_events, buf, sizeof(buf), 0);
-	thread_cancelability(oldstate);
-
-	if (len < 0)
-	{
-		switch (errno)
-		{
-			case EINTR:
-				/* interrupted, try again */
-				return JOB_REQUEUE_DIRECT;
-			case EAGAIN:
-				/* no data ready, select again */
-				return JOB_REQUEUE_DIRECT;
-			default:
-				DBG1(DBG_KNL, "unable to receive from PF_KEY event socket");
-				sleep(1);
-				return JOB_REQUEUE_FAIR;
-		}
-	}
-
-	if (len < sizeof(struct sadb_msg) ||
-		msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg)))
-	{
-		DBG2(DBG_KNL, "received corrupted PF_KEY message");
-		return JOB_REQUEUE_DIRECT;
-	}
-	if (msg->sadb_msg_pid != 0)
-	{	/* not from kernel. not interested, try another one */
-		return JOB_REQUEUE_DIRECT;
-	}
-	if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT)
-	{
-		DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message");
-		return JOB_REQUEUE_DIRECT;
-	}
-
-	switch (msg->sadb_msg_type)
-	{
-		case SADB_ACQUIRE:
-			process_acquire(this, msg);
-			break;
-		case SADB_EXPIRE:
-			/* SADB_EXPIRE events in KLIPS are only triggered by traffic (even
-			 * for the time based limits). So if there is no traffic for a
-			 * longer period than configured as hard limit, we wouldn't be able
-			 * to rekey the SA and just receive the hard expire and thus delete
-			 * the SA.
-			 * To avoid this behavior and to make the daemon behave as with the
-			 * other kernel plugins, we implement the expiration of SAs
-			 * ourselves. */
-			break;
-		case SADB_X_NAT_T_NEW_MAPPING:
-			process_mapping(this, msg);
-			break;
-		default:
-			break;
-	}
-
-	return JOB_REQUEUE_DIRECT;
-}
-
-typedef enum {
-	/** an SPI has expired */
-	EXPIRE_TYPE_SPI,
-	/** a CHILD_SA has to be rekeyed */
-	EXPIRE_TYPE_SOFT,
-	/** a CHILD_SA has to be deleted */
-	EXPIRE_TYPE_HARD
-} expire_type_t;
-
-typedef struct sa_expire_t sa_expire_t;
-
-struct sa_expire_t {
-	/** kernel interface */
-	private_kernel_klips_ipsec_t *this;
-	/** the SPI of the expiring SA */
-	u_int32_t spi;
-	/** the protocol of the expiring SA */
-	u_int8_t protocol;
-	/** the reqid of the expiring SA*/
-	u_int32_t reqid;
-	/** what type of expire this is */
-	expire_type_t type;
-};
-
-/**
- * Called when an SA expires
- */
-static job_requeue_t sa_expires(sa_expire_t *expire)
-{
-	private_kernel_klips_ipsec_t *this = expire->this;
-	u_int8_t protocol = expire->protocol;
-	u_int32_t spi = expire->spi, reqid = expire->reqid;
-	bool hard = expire->type != EXPIRE_TYPE_SOFT;
-	sa_entry_t *cached_sa;
-	linked_list_t *list;
-
-	/* for an expired SPI we first check whether the CHILD_SA got installed
-	 * in the meantime, for expired SAs we check whether they are still installed */
-	list = expire->type == EXPIRE_TYPE_SPI ? this->allocated_spis : this->installed_sas;
-
-	this->mutex->lock(this->mutex);
-	if (list->find_first(list, (linked_list_match_t)sa_entry_match_byid,
-			(void**)&cached_sa, &protocol, &spi, &reqid) != SUCCESS)
-	{
-		/* we found no entry:
-		 * - for SPIs, a CHILD_SA has been installed
-		 * - for SAs, the CHILD_SA has already been deleted */
-		this->mutex->unlock(this->mutex);
-		return JOB_REQUEUE_NONE;
-	}
-	else
-	{
-		list->remove(list, cached_sa, NULL);
-		sa_entry_destroy(cached_sa);
-	}
-	this->mutex->unlock(this->mutex);
-
-	hydra->kernel_interface->expire(hydra->kernel_interface, reqid, protocol,
-									spi, hard);
-	return JOB_REQUEUE_NONE;
-}
-
-/**
- * Schedule an expire job for an SA. Time is in seconds.
- */
-static void schedule_expire(private_kernel_klips_ipsec_t *this,
-							u_int8_t protocol, u_int32_t spi,
-							u_int32_t reqid, expire_type_t type, u_int32_t time)
-{
-	callback_job_t *job;
-	sa_expire_t *expire = malloc_thing(sa_expire_t);
-	expire->this = this;
-	expire->protocol = protocol;
-	expire->spi = spi;
-	expire->reqid = reqid;
-	expire->type = type;
-	job = callback_job_create((callback_job_cb_t)sa_expires, expire, free, NULL);
-	lib->scheduler->schedule_job(lib->scheduler, (job_t*)job, time);
-}
-
-METHOD(kernel_ipsec_t, get_spi, status_t,
-	private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
-	u_int8_t protocol, u_int32_t reqid, u_int32_t *spi)
-{
-	/* we cannot use SADB_GETSPI because KLIPS does not allow us to set the
-	 * NAT-T type in an SADB_UPDATE which we would have to use to update the
-	 * implicitly created SA.
-	 */
-	rng_t *rng;
-	u_int32_t spi_gen;
-
-	rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
-	if (!rng || !rng->get_bytes(rng, sizeof(spi_gen), (void*)&spi_gen))
-	{
-		DBG1(DBG_KNL, "allocating SPI failed");
-		DESTROY_IF(rng);
-		return FAILED;
-	}
-	rng->destroy(rng);
-
-	/* allocated SPIs lie within the range from 0xc0000000 to 0xcFFFFFFF */
-	spi_gen = 0xc0000000 | (spi_gen & 0x0FFFFFFF);
-
-	*spi = htonl(spi_gen);
-
-	this->mutex->lock(this->mutex);
-	this->allocated_spis->insert_last(this->allocated_spis,
-			create_sa_entry(protocol, *spi, reqid, NULL, NULL, FALSE, TRUE));
-	this->mutex->unlock(this->mutex);
-	schedule_expire(this, protocol, *spi, reqid, EXPIRE_TYPE_SPI, SPI_TIMEOUT);
-
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, get_cpi, status_t,
-	private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
-	u_int32_t reqid, u_int16_t *cpi)
-{
-	return FAILED;
-}
-
-/**
- * Add a pseudo IPIP SA for tunnel mode with KLIPS.
- */
-static status_t add_ipip_sa(private_kernel_klips_ipsec_t *this,
-					   host_t *src, host_t *dst, u_int32_t spi, u_int32_t reqid)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_sa *sa;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "adding pseudo IPIP SA with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_ADD;
-	msg->sadb_msg_satype = SADB_X_SATYPE_IPIP;
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
-	sa->sadb_sa_exttype = SADB_EXT_SA;
-	sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
-	sa->sadb_sa_spi = spi;
-	sa->sadb_sa_state = SADB_SASTATE_MATURE;
-	PFKEY_EXT_ADD(msg, sa);
-
-	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to add pseudo IPIP SA with SPI %.8x", ntohl(spi));
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to add pseudo IPIP SA with SPI %.8x: %s (%d)",
-				ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-
-	free(out);
-	return SUCCESS;
-}
-
-/**
- * group the IPIP SA required for tunnel mode with the outer SA
- */
-static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this,
-					   host_t *src, host_t *dst, u_int32_t spi,
-					   u_int8_t protocol, u_int32_t reqid)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_sa *sa;
-	struct sadb_x_satype *satype;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "grouping SAs with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_X_GRPSA;
-	msg->sadb_msg_satype = SADB_X_SATYPE_IPIP;
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
-	sa->sadb_sa_exttype = SADB_EXT_SA;
-	sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
-	sa->sadb_sa_spi = spi;
-	sa->sadb_sa_state = SADB_SASTATE_MATURE;
-	PFKEY_EXT_ADD(msg, sa);
-
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
-
-	satype = (struct sadb_x_satype*)PFKEY_EXT_ADD_NEXT(msg);
-	satype->sadb_x_satype_exttype = SADB_X_EXT_SATYPE2;
-	satype->sadb_x_satype_len = PFKEY_LEN(sizeof(struct sadb_x_satype));
-	satype->sadb_x_satype_satype = proto2satype(protocol);
-	PFKEY_EXT_ADD(msg, satype);
-
-	sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg);
-	sa->sadb_sa_exttype = SADB_X_EXT_SA2;
-	sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa));
-	sa->sadb_sa_spi = spi;
-	sa->sadb_sa_state = SADB_SASTATE_MATURE;
-	PFKEY_EXT_ADD(msg, sa);
-
-	add_addr_ext(msg, dst, SADB_X_EXT_ADDRESS_DST2);
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to group SAs with SPI %.8x", ntohl(spi));
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to group SAs with SPI %.8x: %s (%d)",
-				ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-
-	free(out);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, add_sa, status_t,
-	private_kernel_klips_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, bool initiator, bool encap, bool esn,
-	bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	struct sadb_sa *sa;
-	struct sadb_key *key;
-	size_t len;
-
-	if (inbound)
-	{
-		/* for inbound SAs we allocated an SPI via get_spi, so we first check
-		 * whether that SPI has already expired (race condition) */
-		sa_entry_t *alloc_spi;
-		this->mutex->lock(this->mutex);
-		if (this->allocated_spis->find_first(this->allocated_spis,
-				(linked_list_match_t)sa_entry_match_byid, (void**)&alloc_spi,
-					&protocol, &spi, &reqid) != SUCCESS)
-		{
-			this->mutex->unlock(this->mutex);
-			DBG1(DBG_KNL, "allocated SPI %.8x has already expired", ntohl(spi));
-			return FAILED;
-		}
-		else
-		{
-			this->allocated_spis->remove(this->allocated_spis, alloc_spi, NULL);
-			sa_entry_destroy(alloc_spi);
-		}
-		this->mutex->unlock(this->mutex);
-	}
-
-	memset(&request, 0, sizeof(request));
-
-	DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%d}", ntohl(spi), reqid);
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_ADD;
-	msg->sadb_msg_satype = 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;
-	sa->sadb_sa_state = SADB_SASTATE_MATURE;
-	sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
-	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);
-
-	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
-
-	if (enc_alg != ENCR_UNDEFINED)
-	{
-		if (!sa->sadb_sa_encrypt)
-		{
-			DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-				 encryption_algorithm_names, enc_alg);
-			return FAILED;
-		}
-		DBG2(DBG_KNL, "  using encryption algorithm %N with key size %d",
-			 encryption_algorithm_names, enc_alg, enc_key.len * 8);
-
-		key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
-		key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
-		key->sadb_key_bits = enc_key.len * 8;
-		key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len);
-		memcpy(key + 1, enc_key.ptr, enc_key.len);
-
-		PFKEY_EXT_ADD(msg, key);
-	}
-
-	if (int_alg != AUTH_UNDEFINED)
-	{
-		if (!sa->sadb_sa_auth)
-		{
-			DBG1(DBG_KNL, "algorithm %N not supported by kernel!",
-					 integrity_algorithm_names, int_alg);
-			return FAILED;
-		}
-		DBG2(DBG_KNL, "  using integrity algorithm %N with key size %d",
-			 integrity_algorithm_names, int_alg, int_key.len * 8);
-
-		key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg);
-		key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
-		key->sadb_key_bits = int_key.len * 8;
-		key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len);
-		memcpy(key + 1, int_key.ptr, int_key.len);
-
-		PFKEY_EXT_ADD(msg, key);
-	}
-
-	if (ipcomp != IPCOMP_NONE)
-	{
-		/*TODO*/
-	}
-
-	if (encap)
-	{
-		add_encap_ext(msg, src, dst, FALSE);
-	}
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)",
-				ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-	free(out);
-
-	/* for tunnel mode SAs we have to install an additional IPIP SA and
-	 * group the two SAs together */
-	if (mode == MODE_TUNNEL)
-	{
-		if (add_ipip_sa(this, src, dst, spi, reqid) != SUCCESS ||
-			group_ipip_sa(this, src, dst, spi, protocol, reqid) != SUCCESS)
-		{
-			DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
-			return FAILED;
-		}
-	}
-
-	this->mutex->lock(this->mutex);
-	/* we cache this SA for two reasons:
-	 * - in case an SADB_X_NAT_T_MAPPING_NEW event occurs (we need to find the reqid then)
-	 * - to decide if an expired SA is still installed */
-	this->installed_sas->insert_last(this->installed_sas,
-				create_sa_entry(protocol, spi, reqid, src, dst, encap, inbound));
-	this->mutex->unlock(this->mutex);
-
-	/* Although KLIPS supports SADB_EXT_LIFETIME_SOFT/HARD, we handle the lifetime
-	 * of SAs manually in the plugin. Refer to the comments in receive_events()
-	 * for details. */
-	if (lifetime->time.rekey)
-	{
-		schedule_expire(this, protocol, spi, reqid, EXPIRE_TYPE_SOFT, lifetime->time.rekey);
-	}
-
-	if (lifetime->time.life)
-	{
-		schedule_expire(this, protocol, spi, reqid, EXPIRE_TYPE_HARD, lifetime->time.life);
-	}
-
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, update_sa, status_t,
-	private_kernel_klips_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;
-	size_t len;
-
-	/* we can't update the SA if any of the ip addresses have changed.
-	 * that's because we can't use SADB_UPDATE and by deleting and readding the
-	 * SA the sequence numbers would get lost */
-	if (!src->ip_equals(src, new_src) ||
-		!dst->ip_equals(dst, new_dst))
-	{
-		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address changes"
-				" are not supported", ntohl(spi));
-		return NOT_SUPPORTED;
-	}
-
-	/* because KLIPS does not allow us to change the NAT-T type in an SADB_UPDATE,
-	 * we can't update the SA if the encap flag has changed since installing it */
-	if (encap != new_encap)
-	{
-		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: change of UDP"
-				" encapsulation is not supported", ntohl(spi));
-		return NOT_SUPPORTED;
-	}
-
-	DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
-		 ntohl(spi), src, dst, new_src, new_dst);
-
-	memset(&request, 0, sizeof(request));
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_UPDATE;
-	msg->sadb_msg_satype = 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;
-	sa->sadb_sa_encrypt = SADB_EALG_AESCBC; /* ignored */
-	sa->sadb_sa_auth = SADB_AALG_SHA1HMAC; /* ignored */
-	sa->sadb_sa_state = SADB_SASTATE_MATURE;
-	PFKEY_EXT_ADD(msg, sa);
-
-	add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
-
-	add_encap_ext(msg, new_src, new_dst, TRUE);
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi));
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)",
-				ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-	free(out);
-
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, query_sa, status_t,
-	private_kernel_klips_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)
-{
-	return NOT_SUPPORTED;  /* TODO */
-}
-
-METHOD(kernel_ipsec_t, del_sa, status_t,
-	private_kernel_klips_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;
-	sa_entry_t *cached_sa;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	/* all grouped SAs are automatically deleted by KLIPS as soon as
-	 * one of them is deleted, therefore we delete only the main one */
-	DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
-
-	this->mutex->lock(this->mutex);
-	/* this should not fail, but we don't care if it does, let the kernel decide
-	 * whether this SA exists or not */
-	if (this->installed_sas->find_first(this->installed_sas,
-			(linked_list_match_t)sa_entry_match_bydst, (void**)&cached_sa,
-			&protocol, &spi, dst) == SUCCESS)
-	{
-		this->installed_sas->remove(this->installed_sas, cached_sa, NULL);
-		sa_entry_destroy(cached_sa);
-	}
-	this->mutex->unlock(this->mutex);
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_DELETE;
-	msg->sadb_msg_satype = 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 an SADB_EXT_ADDRESS_SRC to be present even though
-	 * it is not used for anything. */
-	add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC);
-	add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST);
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)",
-				ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-
-	DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
-	free(out);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, add_policy, status_t,
-	private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
-	traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
-	policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
-	mark_t mark, policy_priority_t priority)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	policy_entry_t *policy, *found = NULL;
-	u_int32_t spi;
-	u_int8_t satype;
-	size_t len;
-
-	if (direction == POLICY_FWD)
-	{
-		/* no forward policies for KLIPS */
-		return SUCCESS;
-	}
-
-	/* tunnel mode policies direct the packets into the pseudo IPIP SA */
-	satype = (sa->mode == MODE_TUNNEL) ? SADB_X_SATYPE_IPIP
-									   : proto2satype(sa->esp.use ? IPPROTO_ESP
-																  : IPPROTO_AH);
-	spi = sa->esp.use ? sa->esp.spi : sa->ah.spi;
-
-	/* create a policy */
-	policy = create_policy_entry(src_ts, dst_ts, direction);
-
-	/* find a matching policy */
-	this->mutex->lock(this->mutex);
-	if (this->policies->find_first(this->policies,
-			(linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS)
-	{
-		/* use existing policy */
-		DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing"
-					  " refcount", src_ts, dst_ts,
-					   policy_dir_names, direction);
-		policy_entry_destroy(policy);
-		policy = found;
-	}
-	else
-	{
-		/* apply the new one, if we have no such policy */
-		this->policies->insert_first(this->policies, policy);
-	}
-
-	if (priority == POLICY_PRIORITY_ROUTED)
-	{
-		/* we install this as a %trap eroute in the kernel, later to be
-		 * triggered by packets matching the policy (-> ACQUIRE). */
-		spi = htonl(SPI_TRAP);
-		satype = SADB_X_SATYPE_INT;
-
-		/* the reqid is always set to the latest child SA that trapped this
-		 * policy. we will need this reqid upon receiving an acquire. */
-		policy->reqid = sa->reqid;
-
-		/* increase the trap counter */
-		policy->trapcount++;
-
-		if (policy->activecount)
-		{
-			/* we do not replace the current policy in the kernel while a
-			 * policy is actively used */
-			this->mutex->unlock(this->mutex);
-			return SUCCESS;
-		}
-	}
-	else
-	{
-		/* increase the reference counter */
-		policy->activecount++;
-	}
-
-	DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
-				   policy_dir_names, direction);
-
-	memset(&request, 0, sizeof(request));
-
-	msg = (struct sadb_msg*)request;
-
-	/* FIXME: SADB_X_SAFLAGS_INFLOW may be required, if we add an inbound policy for an IPIP SA */
-	build_addflow(msg, satype, spi,
-				  priority == POLICY_PRIORITY_ROUTED ? NULL : src,
-				  priority == POLICY_PRIORITY_ROUTED ? NULL : dst,
-				  policy->src.net, policy->src.mask, policy->dst.net,
-				  policy->dst.mask, policy->src.proto, found != NULL);
-
-	this->mutex->unlock(this->mutex);
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to add policy %R === %R %N", src_ts, dst_ts,
-					   policy_dir_names, direction);
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to add policy %R === %R %N: %s (%d)", src_ts, dst_ts,
-					   policy_dir_names, direction,
-					   strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-	free(out);
-
-	this->mutex->lock(this->mutex);
-
-	/* we try to find the policy again and install the route if needed */
-	if (this->policies->find_first(this->policies, NULL,
-								  (void**)&policy) != SUCCESS)
-	{
-		this->mutex->unlock(this->mutex);
-		DBG2(DBG_KNL, "the policy %R === %R %N is already gone, ignoring",
-				src_ts, dst_ts, policy_dir_names, direction);
-		return SUCCESS;
-	}
-
-	/* KLIPS requires a special route that directs traffic that matches this
-	 * policy to one of the virtual ipsec interfaces. The virtual interface
-	 * has to be attached to the physical one the traffic runs over.
-	 * This is a special case of the source route we install in other kernel
-	 * interfaces.
-	 * In the following cases we do NOT install a source route (but just a
-	 * regular route):
-	 * - we are not in tunnel mode
-	 * - we are using IPv6 (does not work correctly yet!)
-	 * - routing is disabled via strongswan.conf
-	 */
-	if (policy->route == NULL && direction == POLICY_OUT)
-	{
-		char *iface = NULL;
-		ipsec_dev_t *dev;
-		route_entry_t *route = malloc_thing(route_entry_t);
-		route->src_ip = NULL;
-
-		if (sa->mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6 &&
-			this->install_routes)
-		{
-			hydra->kernel_interface->get_address_by_ts(hydra->kernel_interface,
-												src_ts, &route->src_ip, NULL);
-		}
-
-		if (!route->src_ip)
-		{
-			route->src_ip = host_create_any(src->get_family(src));
-		}
-
-		/* find the virtual interface */
-		hydra->kernel_interface->get_interface(hydra->kernel_interface,
-											   src, &iface);
-		if (find_ipsec_dev(this, iface, &dev) == SUCCESS)
-		{
-			/* above, we got either the name of a virtual or a physical
-			 * interface. for both cases it means we already have the devices
-			 * properly attached (assuming that we are exclusively attaching
-			 * ipsec devices). */
-			dev->refcount++;
-		}
-		else
-		{
-			/* there is no record of a mapping with the returned interface.
-			 * thus, we attach the first free virtual interface we find to
-			 * it. As above we assume we are the only client fiddling with
-			 * ipsec devices. */
-			if (this->ipsec_devices->find_first(this->ipsec_devices,
-					(linked_list_match_t)ipsec_dev_match_free,
-						(void**)&dev) == SUCCESS)
-			{
-				if (attach_ipsec_dev(dev->name, iface) == SUCCESS)
-				{
-					strncpy(dev->phys_name, iface, IFNAMSIZ);
-					dev->refcount = 1;
-				}
-				else
-				{
-					DBG1(DBG_KNL, "failed to attach virtual interface %s"
-							" to %s", dev->name, iface);
-					this->mutex->unlock(this->mutex);
-					free(iface);
-					return FAILED;
-				}
-			}
-			else
-			{
-				this->mutex->unlock(this->mutex);
-				DBG1(DBG_KNL, "failed to attach a virtual interface to %s: no"
-						" virtual interfaces left", iface);
-				free(iface);
-				return FAILED;
-			}
-		}
-		free(iface);
-		route->if_name = strdup(dev->name);
-
-		/* get the nexthop to dst */
-		route->gateway = hydra->kernel_interface->get_nexthop(
-								hydra->kernel_interface, dst, route->src_ip);
-		route->dst_net = chunk_clone(policy->dst.net->get_address(policy->dst.net));
-		route->prefixlen = policy->dst.mask;
-
-		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 route for policy %R === %R",
-					 src_ts, dst_ts);
-				/* FALL */
-			case ALREADY_DONE:
-				/* route exists, do not uninstall */
-				route_entry_destroy(route);
-				break;
-			case SUCCESS:
-				/* cache the installed route */
-				policy->route = route;
-				break;
-		}
-	}
-
-	this->mutex->unlock(this->mutex);
-
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, query_policy, status_t,
-	private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
-	traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
-	time_t *use_time)
-{
-	#define IDLE_PREFIX "idle="
-	static const char *path_eroute = "/proc/net/ipsec_eroute";
-	static const char *path_spi = "/proc/net/ipsec_spi";
-	FILE *file;
-	char line[1024], src[INET6_ADDRSTRLEN + 9], dst[INET6_ADDRSTRLEN + 9];
-	char *said = NULL, *pos;
-	policy_entry_t *policy, *found = NULL;
-	status_t status = FAILED;
-
-	if (direction == POLICY_FWD)
-	{
-		/* we do not install forward policies */
-		return FAILED;
-	}
-
-	DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
-				   policy_dir_names, direction);
-
-	/* create a policy */
-	policy = create_policy_entry(src_ts, dst_ts, direction);
-
-	/* find a matching policy */
-	this->mutex->lock(this->mutex);
-	if (this->policies->find_first(this->policies,
-			(linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
-	{
-		this->mutex->unlock(this->mutex);
-		DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts,
-					   dst_ts, policy_dir_names, direction);
-		policy_entry_destroy(policy);
-		return NOT_FOUND;
-	}
-	policy_entry_destroy(policy);
-	policy = found;
-
-	/* src and dst selectors in KLIPS are of the form NET_ADDR/NETBITS:PROTO */
-	snprintf(src, sizeof(src), "%H/%d:%d", policy->src.net, policy->src.mask,
-			policy->src.proto);
-	src[sizeof(src) - 1] = '\0';
-	snprintf(dst, sizeof(dst), "%H/%d:%d", policy->dst.net, policy->dst.mask,
-			policy->dst.proto);
-	dst[sizeof(dst) - 1] = '\0';
-
-	this->mutex->unlock(this->mutex);
-
-	/* we try to find the matching eroute first */
-	file = fopen(path_eroute, "r");
-	if (file == NULL)
-	{
-		DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
-				dst_ts, policy_dir_names, direction, strerror(errno), errno);
-		return FAILED;
-	}
-
-	/* read line by line where each line looks like:
-	 * packets  src  ->  dst  =>  said */
-	while (fgets(line, sizeof(line), file))
-	{
-		enumerator_t *enumerator;
-		char *token;
-		int i = 0;
-
-		enumerator = enumerator_create_token(line, " \t", " \t\n");
-		while (enumerator->enumerate(enumerator, &token))
-		{
-			switch (i++)
-			{
-				case 0: /* packets */
-					continue;
-				case 1: /* src */
-					if (streq(token, src))
-					{
-						continue;
-					}
-					break;
-				case 2: /* -> */
-					continue;
-				case 3: /* dst */
-					if (streq(token, dst))
-					{
-						continue;
-					}
-					break;
-				case 4: /* => */
-					continue;
-				case 5: /* said */
-					said = strdup(token);
-					break;
-			}
-			break;
-		}
-		enumerator->destroy(enumerator);
-
-		if (i == 5)
-		{
-			/* eroute matched */
-			break;
-		}
-	}
-	fclose(file);
-
-	if (said == NULL)
-	{
-		DBG1(DBG_KNL, "unable to query policy %R === %R %N: found no matching"
-				" eroute", src_ts, dst_ts, policy_dir_names, direction);
-		return FAILED;
-	}
-
-	/* compared with the one in the spi entry the SA ID from the eroute entry
-	 * has an additional ":PROTO" appended, which we need to cut off */
-	pos = strrchr(said, ':');
-	*pos = '\0';
-
-	/* now we try to find the matching spi entry */
-	file = fopen(path_spi, "r");
-	if (file == NULL)
-	{
-		DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts,
-				dst_ts, policy_dir_names, direction, strerror(errno), errno);
-		return FAILED;
-	}
-
-	while (fgets(line, sizeof(line), file))
-	{
-		if (strpfx(line, said))
-		{
-			/* fine we found the correct line, now find the idle time */
-			u_int32_t idle_time;
-			pos = strstr(line, IDLE_PREFIX);
-			if (pos == NULL)
-			{
-				/* no idle time, i.e. this SA has not been used yet */
-				break;
-			}
-			if (sscanf(pos, IDLE_PREFIX"%u", &idle_time) <= 0)
-			{
-				/* idle time not valid */
-				break;
-			}
-
-			*use_time = time_monotonic(NULL) - idle_time;
-			status = SUCCESS;
-			break;
-		}
-	}
-	fclose(file);
-	free(said);
-
-	return status;
-}
-
-METHOD(kernel_ipsec_t, del_policy, status_t,
-	private_kernel_klips_ipsec_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 priority)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg = (struct sadb_msg*)request, *out;
-	policy_entry_t *policy, *found = NULL;
-	route_entry_t *route;
-	size_t len;
-
-	if (direction == POLICY_FWD)
-	{
-		/* no forward policies for KLIPS */
-		return SUCCESS;
-	}
-
-	DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
-				   policy_dir_names, direction);
-
-	/* create a policy */
-	policy = create_policy_entry(src_ts, dst_ts, direction);
-
-	/* find a matching policy */
-	this->mutex->lock(this->mutex);
-	if (this->policies->find_first(this->policies,
-			(linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS)
-	{
-		this->mutex->unlock(this->mutex);
-		DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
-					   dst_ts, policy_dir_names, direction);
-		policy_entry_destroy(policy);
-		return NOT_FOUND;
-	}
-	policy_entry_destroy(policy);
-
-	/* decrease appropriate counter */
-	priority == POLICY_PRIORITY_ROUTED ? found->trapcount--
-									   : found->activecount--;
-
-	if (found->trapcount == 0)
-	{
-		/* if this policy is finally unrouted, we reset the reqid because it
-		 * may still be actively used and there might be a pending acquire for
-		 * this policy. */
-		found->reqid = 0;
-	}
-
-	if (found->activecount > 0)
-	{
-		/* is still used by SAs, keep in kernel */
-		this->mutex->unlock(this->mutex);
-		DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
-		return SUCCESS;
-	}
-	else if (found->activecount == 0 && found->trapcount > 0)
-	{
-		/* for a policy that is not used actively anymore, but is still trapped
-		 * by another child SA we replace the current eroute with a %trap eroute */
-		DBG2(DBG_KNL, "policy still routed by another CHILD_SA, not removed");
-		memset(&request, 0, sizeof(request));
-		build_addflow(msg, SADB_X_SATYPE_INT, htonl(SPI_TRAP), NULL, NULL,
-				found->src.net, found->src.mask, found->dst.net,
-				found->dst.mask, found->src.proto, TRUE);
-		this->mutex->unlock(this->mutex);
-		return pfkey_send_ack(this, msg);
-	}
-
-	/* remove if last reference */
-	this->policies->remove(this->policies, found, NULL);
-	policy = found;
-
-	this->mutex->unlock(this->mutex);
-
-	memset(&request, 0, sizeof(request));
-
-	build_delflow(msg, 0, policy->src.net, policy->src.mask, policy->dst.net,
-			policy->dst.mask, policy->src.proto);
-
-	route = policy->route;
-	policy->route = NULL;
-	policy_entry_destroy(policy);
-
-	if (pfkey_send(this, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
-					   policy_dir_names, direction);
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts,
-					   dst_ts, policy_dir_names, direction,
-					   strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-	free(out);
-
-	if (route)
-	{
-		ipsec_dev_t *dev;
-
-		if (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);
-		}
-
-		/* we have to detach the ipsec interface from the physical one over which
-		 * this SA ran (if it is not used by any other) */
-		this->mutex->lock(this->mutex);
-
-		if (find_ipsec_dev(this, route->if_name, &dev) == SUCCESS)
-		{
-			/* fine, we found a matching device object, let's check if we have
-			 * to detach it. */
-			if (--dev->refcount == 0)
-			{
-				if (detach_ipsec_dev(dev->name, dev->phys_name) != SUCCESS)
-				{
-					DBG1(DBG_KNL, "failed to detach virtual interface %s"
-							" from %s", dev->name, dev->phys_name);
-				}
-				dev->phys_name[0] = '\0';
-			}
-		}
-
-		this->mutex->unlock(this->mutex);
-
-		route_entry_destroy(route);
-	}
-
-	return SUCCESS;
-}
-
-/**
- * Initialize the list of ipsec devices
- */
-static void init_ipsec_devices(private_kernel_klips_ipsec_t *this)
-{
-	int i, count = lib->settings->get_int(lib->settings,
-									"%s.plugins.kernel-klips.ipsec_dev_count",
-									DEFAULT_IPSEC_DEV_COUNT, lib->ns);
-
-	for (i = 0; i < count; ++i)
-	{
-		ipsec_dev_t *dev = malloc_thing(ipsec_dev_t);
-		snprintf(dev->name, IFNAMSIZ, IPSEC_DEV_PREFIX"%d", i);
-		dev->name[IFNAMSIZ - 1] = '\0';
-		dev->phys_name[0] = '\0';
-		dev->refcount = 0;
-		this->ipsec_devices->insert_last(this->ipsec_devices, dev);
-
-		/* detach any previously attached ipsec device */
-		detach_ipsec_dev(dev->name, dev->phys_name);
-	}
-}
-
-/**
- * Register a socket for ACQUIRE/EXPIRE messages
- */
-static status_t register_pfkey_socket(private_kernel_klips_ipsec_t *this, u_int8_t satype)
-{
-	unsigned char request[PFKEY_BUFFER_SIZE];
-	struct sadb_msg *msg, *out;
-	size_t len;
-
-	memset(&request, 0, sizeof(request));
-
-	msg = (struct sadb_msg*)request;
-	msg->sadb_msg_version = PF_KEY_V2;
-	msg->sadb_msg_type = SADB_REGISTER;
-	msg->sadb_msg_satype = satype;
-	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
-
-	if (pfkey_send_socket(this, this->socket_events, msg, &out, &len) != SUCCESS)
-	{
-		DBG1(DBG_KNL, "unable to register PF_KEY socket");
-		return FAILED;
-	}
-	else if (out->sadb_msg_errno)
-	{
-		DBG1(DBG_KNL, "unable to register PF_KEY socket: %s (%d)",
-					   strerror(out->sadb_msg_errno), out->sadb_msg_errno);
-		free(out);
-		return FAILED;
-	}
-	free(out);
-	return SUCCESS;
-}
-
-METHOD(kernel_ipsec_t, destroy, void,
-	private_kernel_klips_ipsec_t *this)
-{
-	if (this->socket > 0)
-	{
-		close(this->socket);
-	}
-	if (this->socket_events > 0)
-	{
-		close(this->socket_events);
-	}
-	this->mutex_pfkey->destroy(this->mutex_pfkey);
-	this->mutex->destroy(this->mutex);
-	this->ipsec_devices->destroy_function(this->ipsec_devices, (void*)ipsec_dev_destroy);
-	this->installed_sas->destroy_function(this->installed_sas, (void*)sa_entry_destroy);
-	this->allocated_spis->destroy_function(this->allocated_spis, (void*)sa_entry_destroy);
-	this->policies->destroy_function(this->policies, (void*)policy_entry_destroy);
-	free(this);
-}
-
-/*
- * Described in header.
- */
-kernel_klips_ipsec_t *kernel_klips_ipsec_create()
-{
-	private_kernel_klips_ipsec_t *this;
-
-	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 = (void*)return_failed,
-				.add_policy = _add_policy,
-				.query_policy = _query_policy,
-				.del_policy = _del_policy,
-				.flush_policies = (void*)return_failed,
-				/* KLIPS does not need a bypass policy for IKE */
-				.bypass_socket = (void*)return_true,
-				/* KLIPS does not need enabling UDP decap explicitly */
-				.enable_udp_decap = (void*)return_true,
-				.destroy = _destroy,
-			},
-		},
-		.policies = linked_list_create(),
-		.allocated_spis = linked_list_create(),
-		.installed_sas = linked_list_create(),
-		.ipsec_devices = linked_list_create(),
-		.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),
-	);
-
-	/* initialize ipsec devices */
-	init_ipsec_devices(this);
-
-	/* create a PF_KEY socket to communicate with the kernel */
-	this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
-	if (this->socket <= 0)
-	{
-		DBG1(DBG_KNL, "unable to create PF_KEY socket");
-		destroy(this);
-		return NULL;
-	}
-
-	/* 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;
-	}
-
-	/* 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->processor->queue_job(lib->processor,
-		(job_t*)callback_job_create_with_prio((callback_job_cb_t)receive_events,
-			this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
-
-	return &this->public;
-}
diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.h b/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.h
deleted file mode 100644
index 306ec0a..0000000
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_ipsec.h
+++ /dev/null
@@ -1,46 +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_klips_ipsec_i kernel_klips_ipsec
- * @{ @ingroup kernel_klips
- */
-
-#ifndef KERNEL_KLIPS_IPSEC_H_
-#define KERNEL_KLIPS_IPSEC_H_
-
-#include <kernel/kernel_ipsec.h>
-
-typedef struct kernel_klips_ipsec_t kernel_klips_ipsec_t;
-
-/**
- * Implementation of the kernel ipsec interface using PF_KEY.
- */
-struct kernel_klips_ipsec_t {
-
-	/**
-	 * Implements kernel_ipsec_t interface
-	 */
-	kernel_ipsec_t interface;
-};
-
-/**
- * Create a PF_KEY kernel ipsec interface instance.
- *
- * @return			kernel_klips_ipsec_t instance
- */
-kernel_klips_ipsec_t *kernel_klips_ipsec_create();
-
-#endif /** KERNEL_KLIPS_IPSEC_H_ @}*/
diff --git a/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.c b/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.c
deleted file mode 100644
index ab02ba7..0000000
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.c
+++ /dev/null
@@ -1,76 +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_klips_plugin.h"
-
-#include "kernel_klips_ipsec.h"
-
-#include <hydra.h>
-
-typedef struct private_kernel_klips_plugin_t private_kernel_klips_plugin_t;
-
-/**
- * private data of kernel PF_KEY plugin
- */
-struct private_kernel_klips_plugin_t {
-	/**
-	 * implements plugin interface
-	 */
-	kernel_klips_plugin_t public;
-};
-
-METHOD(plugin_t, get_name, char*,
-	private_kernel_klips_plugin_t *this)
-{
-	return "kernel-klips";
-}
-
-METHOD(plugin_t, get_features, int,
-	private_kernel_klips_plugin_t *this, plugin_feature_t *features[])
-{
-	static plugin_feature_t f[] = {
-		PLUGIN_CALLBACK(kernel_ipsec_register, kernel_klips_ipsec_create),
-			PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
-	};
-	*features = f;
-	return countof(f);
-}
-
-METHOD(plugin_t, destroy, void,
-	private_kernel_klips_plugin_t *this)
-{
-	free(this);
-}
-
-/*
- * see header file
- */
-plugin_t *kernel_klips_plugin_create()
-{
-	private_kernel_klips_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_klips/kernel_klips_plugin.h b/src/libhydra/plugins/kernel_klips/kernel_klips_plugin.h
deleted file mode 100644
index 8dd386a..0000000
--- a/src/libhydra/plugins/kernel_klips/kernel_klips_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_klips kernel_klips
- * @ingroup hplugins
- *
- * @defgroup kernel_klips_plugin kernel_klips_plugin
- * @{ @ingroup kernel_klips
- */
-
-#ifndef KERNEL_KLIPS_PLUGIN_H_
-#define KERNEL_KLIPS_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct kernel_klips_plugin_t kernel_klips_plugin_t;
-
-/**
- * PF_KEY kernel interface plugin
- */
-struct kernel_klips_plugin_t {
-
-	/**
-	 * implements plugin interface
-	 */
-	plugin_t plugin;
-};
-
-#endif /** KERNEL_KLIPS_PLUGIN_H_ @}*/
diff --git a/src/libhydra/plugins/kernel_klips/pfkeyv2.h b/src/libhydra/plugins/kernel_klips/pfkeyv2.h
deleted file mode 100644
index 20d1c29..0000000
--- a/src/libhydra/plugins/kernel_klips/pfkeyv2.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
-RFC 2367               PF_KEY Key Management API               July 1998
-
-
-Appendix D: Sample Header File
-
-This file defines structures and symbols for the PF_KEY Version 2
-key management interface. It was written at the U.S. Naval Research
-Laboratory. This file is in the public domain. The authors ask that
-you leave this credit intact on any copies of this file.
-*/
-#ifndef __PFKEY_V2_H
-#define __PFKEY_V2_H 1
-
-#define PF_KEY_V2 2
-#define PFKEYV2_REVISION        199806L
-
-#define SADB_RESERVED    0
-#define SADB_GETSPI      1
-#define SADB_UPDATE      2
-#define SADB_ADD         3
-#define SADB_DELETE      4
-#define SADB_GET         5
-#define SADB_ACQUIRE     6
-#define SADB_REGISTER    7
-#define SADB_EXPIRE      8
-#define SADB_FLUSH       9
-#define SADB_DUMP       10
-#define SADB_X_PROMISC  11
-#define SADB_X_PCHANGE  12
-#define SADB_X_GRPSA    13
-#define SADB_X_ADDFLOW	14
-#define SADB_X_DELFLOW	15
-#define SADB_X_DEBUG	16
-#define SADB_X_NAT_T_NEW_MAPPING  17
-#define SADB_MAX                  17
-
-struct sadb_msg {
-  uint8_t sadb_msg_version;
-  uint8_t sadb_msg_type;
-  uint8_t sadb_msg_errno;
-  uint8_t sadb_msg_satype;
-  uint16_t sadb_msg_len;
-  uint16_t sadb_msg_reserved;
-  uint32_t sadb_msg_seq;
-  uint32_t sadb_msg_pid;
-};
-
-struct sadb_ext {
-  uint16_t sadb_ext_len;
-  uint16_t sadb_ext_type;
-};
-
-struct sadb_sa {
-  uint16_t sadb_sa_len;
-  uint16_t sadb_sa_exttype;
-  uint32_t sadb_sa_spi;
-  uint8_t sadb_sa_replay;
-  uint8_t sadb_sa_state;
-  uint8_t sadb_sa_auth;
-  uint8_t sadb_sa_encrypt;
-  uint32_t sadb_sa_flags;
-};
-
-struct sadb_lifetime {
-  uint16_t sadb_lifetime_len;
-  uint16_t sadb_lifetime_exttype;
-  uint32_t sadb_lifetime_allocations;
-  uint64_t sadb_lifetime_bytes;
-  uint64_t sadb_lifetime_addtime;
-  uint64_t sadb_lifetime_usetime;
-  uint32_t sadb_x_lifetime_packets;
-  uint32_t sadb_x_lifetime_reserved;
-};
-
-struct sadb_address {
-  uint16_t sadb_address_len;
-  uint16_t sadb_address_exttype;
-  uint8_t sadb_address_proto;
-  uint8_t sadb_address_prefixlen;
-  uint16_t sadb_address_reserved;
-};
-
-struct sadb_key {
-  uint16_t sadb_key_len;
-  uint16_t sadb_key_exttype;
-  uint16_t sadb_key_bits;
-  uint16_t sadb_key_reserved;
-};
-
-struct sadb_ident {
-  uint16_t sadb_ident_len;
-  uint16_t sadb_ident_exttype;
-  uint16_t sadb_ident_type;
-  uint16_t sadb_ident_reserved;
-  uint64_t sadb_ident_id;
-};
-
-struct sadb_sens {
-  uint16_t sadb_sens_len;
-  uint16_t sadb_sens_exttype;
-  uint32_t sadb_sens_dpd;
-  uint8_t sadb_sens_sens_level;
-  uint8_t sadb_sens_sens_len;
-  uint8_t sadb_sens_integ_level;
-  uint8_t sadb_sens_integ_len;
-  uint32_t sadb_sens_reserved;
-};
-
-struct sadb_prop {
-  uint16_t sadb_prop_len;
-  uint16_t sadb_prop_exttype;
-  uint8_t sadb_prop_replay;
-  uint8_t sadb_prop_reserved[3];
-};
-
-struct sadb_comb {
-  uint8_t sadb_comb_auth;
-  uint8_t sadb_comb_encrypt;
-  uint16_t sadb_comb_flags;
-  uint16_t sadb_comb_auth_minbits;
-  uint16_t sadb_comb_auth_maxbits;
-  uint16_t sadb_comb_encrypt_minbits;
-  uint16_t sadb_comb_encrypt_maxbits;
-  uint32_t sadb_comb_reserved;
-  uint32_t sadb_comb_soft_allocations;
-  uint32_t sadb_comb_hard_allocations;
-  uint64_t sadb_comb_soft_bytes;
-  uint64_t sadb_comb_hard_bytes;
-  uint64_t sadb_comb_soft_addtime;
-  uint64_t sadb_comb_hard_addtime;
-  uint64_t sadb_comb_soft_usetime;
-  uint64_t sadb_comb_hard_usetime;
-  uint32_t sadb_x_comb_soft_packets;
-  uint32_t sadb_x_comb_hard_packets;
-};
-
-struct sadb_supported {
-  uint16_t sadb_supported_len;
-  uint16_t sadb_supported_exttype;
-  uint32_t sadb_supported_reserved;
-};
-
-struct sadb_alg {
-  uint8_t sadb_alg_id;
-  uint8_t sadb_alg_ivlen;
-  uint16_t sadb_alg_minbits;
-  uint16_t sadb_alg_maxbits;
-  uint16_t sadb_alg_reserved;
-};
-
-struct sadb_spirange {
-  uint16_t sadb_spirange_len;
-  uint16_t sadb_spirange_exttype;
-  uint32_t sadb_spirange_min;
-  uint32_t sadb_spirange_max;
-  uint32_t sadb_spirange_reserved;
-};
-
-struct sadb_x_kmprivate {
-  uint16_t sadb_x_kmprivate_len;
-  uint16_t sadb_x_kmprivate_exttype;
-  uint32_t sadb_x_kmprivate_reserved;
-};
-
-struct sadb_x_satype {
-  uint16_t sadb_x_satype_len;
-  uint16_t sadb_x_satype_exttype;
-  uint8_t sadb_x_satype_satype;
-  uint8_t sadb_x_satype_reserved[3];
-};
-
-struct sadb_x_debug {
-  uint16_t sadb_x_debug_len;
-  uint16_t sadb_x_debug_exttype;
-  uint32_t sadb_x_debug_tunnel;
-  uint32_t sadb_x_debug_netlink;
-  uint32_t sadb_x_debug_xform;
-  uint32_t sadb_x_debug_eroute;
-  uint32_t sadb_x_debug_spi;
-  uint32_t sadb_x_debug_radij;
-  uint32_t sadb_x_debug_esp;
-  uint32_t sadb_x_debug_ah;
-  uint32_t sadb_x_debug_rcv;
-  uint32_t sadb_x_debug_pfkey;
-  uint32_t sadb_x_debug_ipcomp;
-  uint32_t sadb_x_debug_verbose;
-  uint8_t sadb_x_debug_reserved[4];
-};
-
-struct sadb_x_nat_t_type {
-  uint16_t sadb_x_nat_t_type_len;
-  uint16_t sadb_x_nat_t_type_exttype;
-  uint8_t sadb_x_nat_t_type_type;
-  uint8_t sadb_x_nat_t_type_reserved[3];
-};
-struct sadb_x_nat_t_port {
-  uint16_t sadb_x_nat_t_port_len;
-  uint16_t sadb_x_nat_t_port_exttype;
-  uint16_t sadb_x_nat_t_port_port;
-  uint16_t sadb_x_nat_t_port_reserved;
-};
-
-/*
- * A protocol structure for passing through the transport level
- * protocol.  It contains more fields than are actually used/needed
- * but it is this way to be compatible with the structure used in
- * OpenBSD (http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/pfkeyv2.h)
- */
-struct sadb_protocol {
-  uint16_t sadb_protocol_len;
-  uint16_t sadb_protocol_exttype;
-  uint8_t  sadb_protocol_proto;
-  uint8_t  sadb_protocol_direction;
-  uint8_t  sadb_protocol_flags;
-  uint8_t  sadb_protocol_reserved2;
-};
-
-#define SADB_EXT_RESERVED             0
-#define SADB_EXT_SA                   1
-#define SADB_EXT_LIFETIME_CURRENT     2
-#define SADB_EXT_LIFETIME_HARD        3
-#define SADB_EXT_LIFETIME_SOFT        4
-#define SADB_EXT_ADDRESS_SRC          5
-#define SADB_EXT_ADDRESS_DST          6
-#define SADB_EXT_ADDRESS_PROXY        7
-#define SADB_EXT_KEY_AUTH             8
-#define SADB_EXT_KEY_ENCRYPT          9
-#define SADB_EXT_IDENTITY_SRC         10
-#define SADB_EXT_IDENTITY_DST         11
-#define SADB_EXT_SENSITIVITY          12
-#define SADB_EXT_PROPOSAL             13
-#define SADB_EXT_SUPPORTED_AUTH       14
-#define SADB_EXT_SUPPORTED_ENCRYPT    15
-#define SADB_EXT_SPIRANGE             16
-#define SADB_X_EXT_KMPRIVATE          17
-#define SADB_X_EXT_SATYPE2            18
-#define SADB_X_EXT_SA2                19
-#define SADB_X_EXT_ADDRESS_DST2       20
-#define SADB_X_EXT_ADDRESS_SRC_FLOW   21
-#define SADB_X_EXT_ADDRESS_DST_FLOW   22
-#define SADB_X_EXT_ADDRESS_SRC_MASK   23
-#define SADB_X_EXT_ADDRESS_DST_MASK   24
-#define SADB_X_EXT_DEBUG              25
-#define SADB_X_EXT_PROTOCOL           26
-#define SADB_X_EXT_NAT_T_TYPE         27
-#define SADB_X_EXT_NAT_T_SPORT        28
-#define SADB_X_EXT_NAT_T_DPORT        29
-#define SADB_X_EXT_NAT_T_OA           30
-#define SADB_EXT_MAX                  30
-
-/* SADB_X_DELFLOW required over and above SADB_X_SAFLAGS_CLEARFLOW */
-#define SADB_X_EXT_ADDRESS_DELFLOW \
-	( (1<<SADB_X_EXT_ADDRESS_SRC_FLOW) \
-	| (1<<SADB_X_EXT_ADDRESS_DST_FLOW) \
-	| (1<<SADB_X_EXT_ADDRESS_SRC_MASK) \
-	| (1<<SADB_X_EXT_ADDRESS_DST_MASK))
-
-#define SADB_SATYPE_UNSPEC    0
-#define SADB_SATYPE_AH        2
-#define SADB_SATYPE_ESP       3
-#define SADB_SATYPE_RSVP      5
-#define SADB_SATYPE_OSPFV2    6
-#define SADB_SATYPE_RIPV2     7
-#define SADB_SATYPE_MIP       8
-#define SADB_X_SATYPE_IPIP    9
-#define SADB_X_SATYPE_COMP    10
-#define SADB_X_SATYPE_INT     11
-#define SADB_SATYPE_MAX       11
-
-#define SADB_SASTATE_LARVAL   0
-#define SADB_SASTATE_MATURE   1
-#define SADB_SASTATE_DYING    2
-#define SADB_SASTATE_DEAD     3
-#define SADB_SASTATE_MAX      3
-
-#define SADB_SAFLAGS_PFS		1
-#define SADB_X_SAFLAGS_REPLACEFLOW	2
-#define SADB_X_SAFLAGS_CLEARFLOW	4
-#define SADB_X_SAFLAGS_INFLOW		8
-
-#define SADB_AALG_NONE        0
-#define SADB_AALG_MD5HMAC     2
-#define SADB_AALG_SHA1HMAC    3
-#define	SADB_AALG_SHA256_HMAC    5
-#define	SADB_AALG_SHA384_HMAC    6
-#define	SADB_AALG_SHA512_HMAC    7
-#define	SADB_AALG_RIPEMD160HMAC      8
-#define	SADB_AALG_MAX         15
-
-#define SADB_EALG_NONE        0
-#define SADB_EALG_DESCBC      2
-#define SADB_EALG_3DESCBC     3
-#define SADB_EALG_BFCBC	      7
-#define SADB_EALG_NULL        11
-#define SADB_EALG_AESCBC      12
-#define SADB_EALG_MAX         255
-
-#define SADB_X_CALG_NONE          0
-#define SADB_X_CALG_OUI           1
-#define SADB_X_CALG_DEFLATE       2
-#define SADB_X_CALG_LZS           3
-#define SADB_X_CALG_V42BIS        4
-#define SADB_X_CALG_MAX           4
-
-#define SADB_X_TALG_NONE          0
-#define SADB_X_TALG_IPv4_in_IPv4  1
-#define SADB_X_TALG_IPv6_in_IPv4  2
-#define SADB_X_TALG_IPv4_in_IPv6  3
-#define SADB_X_TALG_IPv6_in_IPv6  4
-#define SADB_X_TALG_MAX           4
-
-
-#define SADB_IDENTTYPE_RESERVED   0
-#define SADB_IDENTTYPE_PREFIX     1
-#define SADB_IDENTTYPE_FQDN       2
-#define SADB_IDENTTYPE_USERFQDN   3
-#define SADB_X_IDENTTYPE_CONNECTION 4
-#define SADB_IDENTTYPE_MAX        4
-
-#define SADB_KEY_FLAGS_MAX     0
-#endif /* __PFKEY_V2_H */
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.am b/src/libhydra/plugins/kernel_netlink/Makefile.am
index ad57352..c91f9a9 100644
--- a/src/libhydra/plugins/kernel_netlink/Makefile.am
+++ b/src/libhydra/plugins/kernel_netlink/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 	-DROUTING_TABLE_PRIO=${routing_table_prio}
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.in b/src/libhydra/plugins/kernel_netlink/Makefile.in
index 26cde7c..2a67bd5 100644
--- a/src/libhydra/plugins/kernel_netlink/Makefile.in
+++ b/src/libhydra/plugins/kernel_netlink/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-DROUTING_TABLE_PRIO=${routing_table_prio}
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-kernel-netlink.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-kernel-netlink.la
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index c864a92..d9b55cf 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -70,11 +70,8 @@
 #define SOL_UDP IPPROTO_UDP
 #endif
 
-/** Default priority of installed policies */
-#define PRIO_BASE 512
-
-/** Default replay window size, if not set using charon.replay_window */
-#define DEFAULT_REPLAY_WINDOW 32
+/** Base priority for installed policies */
+#define PRIO_BASE 384
 
 /** Default lifetime of an acquire XFRM state (in seconds) */
 #define DEFAULT_ACQUIRE_LIFETIME 165
@@ -180,7 +177,7 @@ static kernel_algorithm_t encryption_algs[] = {
 	{ENCR_3DES,					"des3_ede"			},
 /*	{ENCR_RC5,					"***"				}, */
 /*	{ENCR_IDEA,					"***"				}, */
-	{ENCR_CAST,					"cast128"			},
+	{ENCR_CAST,					"cast5"				},
 	{ENCR_BLOWFISH,				"blowfish"			},
 /*	{ENCR_3IDEA,				"***"				}, */
 /*	{ENCR_DES_IV32,				"***"				}, */
@@ -316,16 +313,6 @@ struct private_kernel_netlink_ipsec_t {
 	 * Whether to track the history of a policy
 	 */
 	bool policy_history;
-
-	/**
-	 * Size of the replay window, in packets (= bits)
-	 */
-	u_int32_t replay_window;
-
-	/**
-	 * Size of the replay window bitmap, in number of __u32 blocks
-	 */
-	u_int32_t replay_bmp;
 };
 
 typedef struct route_entry_t route_entry_t;
@@ -619,6 +606,9 @@ static inline u_int32_t get_priority(policy_entry_t *policy,
 			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 */
@@ -631,14 +621,6 @@ static inline u_int32_t get_priority(policy_entry_t *policy,
 }
 
 /**
- * Return the length of the ESN bitmap
- */
-static inline size_t esn_bmp_len(private_kernel_netlink_ipsec_t *this)
-{
-	return this->replay_bmp * sizeof(u_int32_t);
-}
-
-/**
  * Convert the general ipsec mode to the one defined in xfrm.h
  */
 static u_int8_t mode2kernel(ipsec_mode_t mode)
@@ -1194,8 +1176,9 @@ 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, bool initiator, bool encap, bool esn, bool inbound,
+	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,
 	traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
 {
 	netlink_buf_t request;
@@ -1213,8 +1196,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 		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, initiator, FALSE, FALSE, inbound,
-			   src_ts, dst_ts);
+			   chunk_empty, mode, ipcomp, 0, 0, initiator, FALSE, FALSE,
+			   inbound, src_ts, dst_ts);
 		ipcomp = IPCOMP_NONE;
 		/* use transport mode ESP SA, IPComp uses tunnel mode */
 		mode = MODE_TRANSPORT;
@@ -1480,23 +1463,24 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 
 	if (protocol != IPPROTO_COMP)
 	{
-		if (esn || this->replay_window > DEFAULT_REPLAY_WINDOW)
+		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) + esn_bmp_len(this));
+									 sizeof(*replay) + bmp_size);
 			if (!replay)
 			{
 				goto failed;
 			}
 			/* bmp_len contains number uf __u32's */
-			replay->bmp_len = this->replay_bmp;
-			replay->replay_window = this->replay_window;
-			DBG2(DBG_KNL, "  using replay window of %u packets",
-				 this->replay_window);
+			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)
 			{
@@ -1506,9 +1490,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 		}
 		else
 		{
-			DBG2(DBG_KNL, "  using replay window of %u packets",
-				 this->replay_window);
-			sa->replay_window = this->replay_window;
+			DBG2(DBG_KNL, "  using replay window of %u packets", replay_window);
+			sa->replay_window = replay_window;
 		}
 	}
 
@@ -1542,6 +1525,7 @@ 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)
 {
 	netlink_buf_t request;
@@ -1618,9 +1602,10 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
 				break;
 			}
 			if (rta->rta_type == XFRMA_REPLAY_ESN_VAL &&
-				RTA_PAYLOAD(rta) >= sizeof(**replay_esn) + esn_bmp_len(this))
+				RTA_PAYLOAD(rta) >= sizeof(**replay_esn))
 			{
 				*replay_esn = malloc(RTA_PAYLOAD(rta));
+				*replay_esn_len = RTA_PAYLOAD(rta);
 				memcpy(*replay_esn, RTA_DATA(rta), RTA_PAYLOAD(rta));
 				break;
 			}
@@ -1804,6 +1789,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 	struct xfrm_encap_tmpl* tmpl = NULL;
 	struct xfrm_replay_state *replay = NULL;
 	struct xfrm_replay_state_esn *replay_esn = NULL;
+	u_int32_t replay_esn_len;
 	status_t status = FAILED;
 
 	/* if IPComp is used, we first update the IPComp SA */
@@ -1868,7 +1854,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 		goto failed;
 	}
 
-	get_replay_state(this, spi, protocol, dst, mark, &replay_esn, &replay);
+	get_replay_state(this, spi, protocol, dst, mark, &replay_esn, &replay_esn_len, &replay);
 
 	/* delete the old SA (without affecting the IPComp SA) */
 	if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS)
@@ -1936,12 +1922,12 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 		struct xfrm_replay_state_esn *state;
 
 		state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
-								sizeof(*state) + esn_bmp_len(this));
+								replay_esn_len);
 		if (!state)
 		{
 			goto failed;
 		}
-		memcpy(state, replay_esn, sizeof(*state) + esn_bmp_len(this));
+		memcpy(state, replay_esn, replay_esn_len);
 	}
 	else if (replay)
 	{
@@ -2149,9 +2135,20 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
 				fwd->dst_ts, &route->src_ip, NULL) == SUCCESS)
 		{
 			/* get the nexthop to src (src as we are in POLICY_FWD) */
-			route->gateway = hydra->kernel_interface->get_nexthop(
+			if (!ipsec->src->is_anyaddr(ipsec->src))
+			{
+				route->gateway = hydra->kernel_interface->get_nexthop(
 											hydra->kernel_interface, ipsec->src,
-											ipsec->dst);
+											-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);
 
@@ -2686,13 +2683,8 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
 		.policy_history = TRUE,
 		.install_routes = lib->settings->get_bool(lib->settings,
 							"%s.install_routes", TRUE, lib->ns),
-		.replay_window = lib->settings->get_int(lib->settings,
-							"%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
 	);
 
-	this->replay_bmp = (this->replay_window + sizeof(u_int32_t) * 8 - 1) /
-													(sizeof(u_int32_t) * 8);
-
 	if (streq(lib->ns, "starter"))
 	{	/* starter has no threads, so we do not register for kernel events */
 		register_for_events = FALSE;
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index 3cf3176..82b637d 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2013 Tobias Brunner
+ * Copyright (C) 2008-2014 Tobias Brunner
  * Copyright (C) 2005-2008 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -88,6 +88,9 @@ struct addr_entry_t {
 	/** the ip address */
 	host_t *ip;
 
+	/** address flags */
+	u_char flags;
+
 	/** scope of the address */
 	u_char scope;
 
@@ -467,6 +470,11 @@ struct private_kernel_netlink_net_t {
 	bool rta_prefsrc_for_ipv6;
 
 	/**
+	 * 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;
@@ -653,20 +661,156 @@ static void addr_map_entry_remove(hashtable_t *map, addr_entry_t *addr,
 }
 
 /**
- * get the first non-virtual ip address on the given interface.
- * if a candidate address is given, we first search for that address and if not
+ * 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.
+ * Returned host is a clone, has to be freed by caller.
  *
- * this->lock must be held when calling this function
+ * 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 *candidate)
+									 int ifindex, int family, host_t *dest,
+									 host_t *candidate)
 {
 	iface_entry_t *iface;
 	enumerator_t *addrs;
-	addr_entry_t *addr;
-	host_t *ip = NULL;
+	addr_entry_t *addr, *best = NULL;
 
 	if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index,
 								 (void**)&iface, &ifindex) == SUCCESS)
@@ -676,29 +820,25 @@ static host_t *get_interface_address(private_kernel_netlink_net_t *this,
 			addrs = iface->addrs->create_enumerator(iface->addrs);
 			while (addrs->enumerate(addrs, &addr))
 			{
-				if (addr->refcount)
-				{	/* ignore virtual IP addresses */
+				if (addr->refcount ||
+					addr->ip->get_family(addr->ip) != family)
+				{	/* ignore virtual IP addresses and ensure family matches */
 					continue;
 				}
-				if (addr->ip->get_family(addr->ip) == family)
+				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))
 				{
-					if (!candidate || candidate->ip_equals(candidate, addr->ip))
-					{	/* stop at the first address if we don't search for a
-						 * candidate or if the candidate matches */
-						ip = addr->ip;
-						break;
-					}
-					else if (!ip)
-					{	/* store the first address as fallback if candidate is
-						 * not found */
-						ip = addr->ip;
-					}
+					best = addr;
 				}
 			}
 			addrs->destroy(addrs);
 		}
 	}
-	return ip ? ip->clone(ip) : NULL;
+	return best ? best->ip->clone(best->ip) : NULL;
 }
 
 /**
@@ -989,6 +1129,7 @@ static void process_addr(private_kernel_netlink_net_t *this,
 				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);
@@ -1076,7 +1217,8 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h
 	}
 	if (!host && rta_oif)
 	{
-		host = get_interface_address(this, rta_oif, msg->rtm_family, NULL);
+		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 */
@@ -1318,9 +1460,10 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
 }
 
 /**
- * check if an address (chunk) addr is in subnet (net with net_len net bits)
+ * 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, chunk_t net, int net_len)
+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;
@@ -1329,7 +1472,7 @@ static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len)
 	{	/* any address matches a /0 network */
 		return TRUE;
 	}
-	if (addr.len != net.len || net_len > 8 * net.len )
+	if (addr.len != net.len || net_len > 8 * net.len || prefix < net_len)
 	{
 		return FALSE;
 	}
@@ -1445,7 +1588,8 @@ static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *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,
-						 bool nexthop, host_t *candidate, u_int recursion)
+						 int prefix, bool nexthop, host_t *candidate,
+						 u_int recursion)
 {
 	netlink_buf_t request;
 	struct nlmsghdr *hdr, *out, *current;
@@ -1456,18 +1600,25 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 	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 = (struct nlmsghdr*)request;
 	hdr->nlmsg_flags = NLM_F_REQUEST;
-	if (dest->get_family(dest) == AF_INET || this->rta_prefsrc_for_ipv6 ||
-		this->routing_table)
+	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 */
@@ -1477,19 +1628,22 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 	hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
 
 	msg = (struct rtmsg*)NLMSG_DATA(hdr);
-	msg->rtm_family = dest->get_family(dest);
+	msg->rtm_family = family;
 	if (candidate)
 	{
 		chunk = candidate->get_address(candidate);
 		netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
 	}
-	chunk = dest->get_address(dest);
-	netlink_add_attribute(hdr, RTA_DST, 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 failed",
-			 nexthop ? "nexthop" : "address", dest);
+		DBG2(DBG_KNL, "getting %s to reach %H/%d failed",
+			 nexthop ? "nexthop" : "address", dest, prefix);
 		return NULL;
 	}
 	routes = linked_list_create();
@@ -1524,7 +1678,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 				{	/* interface is down */
 					continue;
 				}
-				if (!addr_in_subnet(chunk, route->dst, route->dst_len))
+				if (!addr_in_subnet(chunk, prefix, route->dst, route->dst_len))
 				{	/* route destination does not contain dest */
 					continue;
 				}
@@ -1580,7 +1734,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 			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, candidate);
+											msg->rtm_family, dest, candidate);
 				if (src && src->ip_equals(src, candidate))
 				{
 					route->src_host->destroy(route->src_host);
@@ -1599,7 +1753,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 		if (route->oif)
 		{	/* no src, but an interface - get address from it */
 			route->src_host = get_interface_address(this, route->oif,
-													msg->rtm_family, candidate);
+											msg->rtm_family, dest, candidate);
 			if (route->src_host)
 			{	/* we handle this address the same as the one above */
 				if (!candidate ||
@@ -1619,7 +1773,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 			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, FALSE, candidate,
+				route->src_host = get_route(this, gtw, -1, FALSE, candidate,
 											recursion + 1);
 			}
 			DESTROY_IF(gtw);
@@ -1643,7 +1797,10 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 		{
 			addr = host_create_from_chunk(msg->rtm_family, best->gtw, 0);
 		}
-		addr = addr ?: dest->clone(dest);
+		if (!addr && !match_net)
+		{	/* fallback to destination address */
+			addr = dest->clone(dest);
+		}
 	}
 	else
 	{
@@ -1658,13 +1815,13 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 
 	if (addr)
 	{
-		DBG2(DBG_KNL, "using %H as %s to reach %H", addr,
-			 nexthop ? "nexthop" : "address", dest);
+		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",
-			 nexthop ? "nexthop" : "address", dest);
+		DBG2(DBG_KNL, "no %s found to reach %H/%d",
+			 nexthop ? "nexthop" : "address", dest, prefix);
 	}
 	return addr;
 }
@@ -1672,13 +1829,13 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 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, FALSE, src, 0);
+	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, host_t *src)
+	private_kernel_netlink_net_t *this, host_t *dest, int prefix, host_t *src)
 {
-	return get_route(this, dest, TRUE, src, 0);
+	return get_route(this, dest, prefix, TRUE, src, 0);
 }
 
 /**
@@ -1711,6 +1868,17 @@ static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type
 
 	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);
 }
 
@@ -2294,6 +2462,8 @@ kernel_netlink_net_t *kernel_netlink_net_create()
 						"%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),
 	);
diff --git a/src/libhydra/plugins/kernel_pfkey/Makefile.am b/src/libhydra/plugins/kernel_pfkey/Makefile.am
index bb5d0d7..f645528 100644
--- a/src/libhydra/plugins/kernel_pfkey/Makefile.am
+++ b/src/libhydra/plugins/kernel_pfkey/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
diff --git a/src/libhydra/plugins/kernel_pfkey/Makefile.in b/src/libhydra/plugins/kernel_pfkey/Makefile.in
index 658ec7b..7677696 100644
--- a/src/libhydra/plugins/kernel_pfkey/Makefile.in
+++ b/src/libhydra/plugins/kernel_pfkey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-kernel-pfkey.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-kernel-pfkey.la
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 4704d41..e1a58aa 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -13,7 +13,29 @@
  * 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>
 
@@ -24,7 +46,6 @@
 #ifdef HAVE_NET_PFKEYV2_H
 #include <net/pfkeyv2.h>
 #else
-#include <stdint.h>
 #include <linux/pfkeyv2.h>
 #endif
 
@@ -114,8 +135,8 @@
 #define SOL_UDP IPPROTO_UDP
 #endif
 
-/** default priority of installed policies */
-#define PRIO_BASE 512
+/** base priority for installed policies */
+#define PRIO_BASE 384
 
 #ifdef __APPLE__
 /** from xnu/bsd/net/pfkeyv2.h */
@@ -562,6 +583,9 @@ static inline u_int32_t get_priority(policy_entry_t *policy,
 			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 */
@@ -825,18 +849,20 @@ static kernel_algorithm_t integrity_algs[] = {
 	{END_OF_LIST,				0,							},
 };
 
-#if 0
 /**
  * Algorithms for IPComp, unused yet
  */
 static kernel_algorithm_t compression_algs[] = {
 /*	{IPCOMP_OUI,				0							}, */
 	{IPCOMP_DEFLATE,			SADB_X_CALG_DEFLATE			},
+#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							},
 };
-#endif
 
 /**
  * Look up a kernel algorithm ID and its key size
@@ -854,6 +880,9 @@ static int lookup_algorithm(transform_type_t type, int ikev2)
 		case INTEGRITY_ALGORITHM:
 			list = integrity_algs;
 			break;
+		case COMPRESSION_ALGORITHM:
+			list = compression_algs;
+			break;
 		default:
 			return 0;
 	}
@@ -1483,9 +1512,13 @@ static bool receive_events(private_kernel_pfkey_ipsec_t *this, int fd,
 	return TRUE;
 }
 
-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 reqid, u_int32_t *spi)
+/**
+ * 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 reqid, u_int32_t *spi)
 {
 	unsigned char request[PFKEY_BUFFER_SIZE];
 	struct sadb_msg *msg, *out;
@@ -1500,7 +1533,7 @@ METHOD(kernel_ipsec_t, get_spi, status_t,
 	msg = (struct sadb_msg*)request;
 	msg->sadb_msg_version = PF_KEY_V2;
 	msg->sadb_msg_type = SADB_GETSPI;
-	msg->sadb_msg_satype = proto2satype(protocol);
+	msg->sadb_msg_satype = proto2satype(proto);
 	msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
 
 	sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg);
@@ -1515,8 +1548,8 @@ METHOD(kernel_ipsec_t, get_spi, status_t,
 	range = (struct sadb_spirange*)PFKEY_EXT_ADD_NEXT(msg);
 	range->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
 	range->sadb_spirange_len = PFKEY_LEN(sizeof(struct sadb_spirange));
-	range->sadb_spirange_min = 0xc0000000;
-	range->sadb_spirange_max = 0xcFFFFFFF;
+	range->sadb_spirange_min = min;
+	range->sadb_spirange_max = max;
 	PFKEY_EXT_ADD(msg, range);
 
 	if (pfkey_send(this, msg, &out, &len) == SUCCESS)
@@ -1542,11 +1575,42 @@ METHOD(kernel_ipsec_t, get_spi, status_t,
 	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 reqid, u_int32_t *spi)
+{
+	DBG2(DBG_KNL, "getting SPI for reqid {%u}", reqid);
+
+	if (get_spi_internal(this, src, dst, protocol,
+						 0xc0000000, 0xcFFFFFFF, reqid, spi) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get SPI for reqid {%u}", reqid);
+		return FAILED;
+	}
+
+	DBG2(DBG_KNL, "got SPI %.8x for reqid {%u}", ntohl(*spi), reqid);
+	return SUCCESS;
+}
+
 METHOD(kernel_ipsec_t, get_cpi, status_t,
 	private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
 	u_int32_t reqid, u_int16_t *cpi)
 {
-	return FAILED;
+	u_int32_t received_spi = 0;
+
+	DBG2(DBG_KNL, "getting CPI for reqid {%u}", reqid);
+
+	if (get_spi_internal(this, src, dst, IPPROTO_COMP,
+						 0x100, 0xEFFF, reqid, &received_spi) != SUCCESS)
+	{
+		DBG1(DBG_KNL, "unable to get CPI for reqid {%u}", reqid);
+		return FAILED;
+	}
+
+	*cpi = htons((u_int16_t)ntohl(received_spi));
+
+	DBG2(DBG_KNL, "got CPI %.4x for reqid {%u}", ntohs(*cpi), reqid);
+	return SUCCESS;
 }
 
 METHOD(kernel_ipsec_t, add_sa, status_t,
@@ -1554,8 +1618,9 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 	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, bool initiator, bool encap, bool esn,
-	bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+	u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window,
+	bool initiator, bool encap, bool esn, bool inbound,
+	traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
 {
 	unsigned char request[PFKEY_BUFFER_SIZE];
 	struct sadb_msg *msg, *out;
@@ -1565,6 +1630,20 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 	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,
+			   NULL, NULL);
+		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}",
@@ -1595,9 +1674,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 	sa->sadb_sa_exttype = SADB_EXT_SA;
 	sa->sadb_sa_len = PFKEY_LEN(len);
 	sa->sadb_sa_spi = spi;
-	sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32;
-	sa->sadb_sa_auth = lookup_algorithm(INTEGRITY_ALGORITHM, int_alg);
-	sa->sadb_sa_encrypt = lookup_algorithm(ENCRYPTION_ALGORITHM, enc_alg);
+	if (protocol == IPPROTO_COMP)
+	{
+		sa->sadb_sa_encrypt = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
+	}
+	else
+	{
+		sa->sadb_sa_replay = min(replay_window, 32);
+		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);
@@ -1668,11 +1754,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 		PFKEY_EXT_ADD(msg, key);
 	}
 
-	if (ipcomp != IPCOMP_NONE)
-	{
-		/*TODO*/
-	}
-
 #ifdef HAVE_NATT
 	if (encap)
 	{
@@ -1719,6 +1800,13 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 		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));
@@ -1919,6 +2007,12 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
 	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));
@@ -2018,7 +2112,7 @@ static void add_exclude_route(private_kernel_pfkey_ipsec_t *this,
 	{
 		DBG2(DBG_KNL, "installing new exclude route for %H src %H", dst, src);
 		gtw = hydra->kernel_interface->get_nexthop(hydra->kernel_interface,
-												   dst, NULL);
+												   dst, -1, NULL);
 		if (gtw)
 		{
 			char *if_name = NULL;
@@ -2129,16 +2223,29 @@ static bool install_route(private_kernel_pfkey_ipsec_t *this,
 	INIT(route,
 		.prefixlen = policy->src.mask,
 		.src_ip = host,
-		.gateway = hydra->kernel_interface->get_nexthop(
-											hydra->kernel_interface, dst, src),
 		.dst_net = chunk_clone(policy->src.net->get_address(policy->src.net)),
 	);
 
-	/* 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)
+	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;
 	}
 
@@ -2230,6 +2337,7 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
 	ipsec_sa_t *ipsec = mapping->sa;
 	pfkey_msg_t response;
 	size_t len;
+	ipsec_mode_t proto_mode;
 
 	memset(&request, 0, sizeof(request));
 
@@ -2251,15 +2359,43 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
 
 	/* 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(ipsec->cfg.mode);
+	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 (ipsec->cfg.mode == MODE_TUNNEL)
+	if (proto_mode == MODE_TUNNEL)
 	{
 		len = hostcpy(req + 1, ipsec->src, FALSE);
 		req->sadb_x_ipsecrequest_len += len;
@@ -2324,12 +2460,12 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
 	free(out);
 
 	/* install a route, if:
-	 * - this is a forward policy (to just get one for each child)
-	 * - we are in tunnel mode
+	 * - 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 &&
-		ipsec->cfg.mode != MODE_TRANSPORT && this->install_routes)
+	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);
 	}
diff --git a/src/libhydra/plugins/kernel_pfroute/Makefile.am b/src/libhydra/plugins/kernel_pfroute/Makefile.am
index 9d16213..5129c02 100644
--- a/src/libhydra/plugins/kernel_pfroute/Makefile.am
+++ b/src/libhydra/plugins/kernel_pfroute/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
diff --git a/src/libhydra/plugins/kernel_pfroute/Makefile.in b/src/libhydra/plugins/kernel_pfroute/Makefile.in
index cdb09b1..7938a3d 100644
--- a/src/libhydra/plugins/kernel_pfroute/Makefile.in
+++ b/src/libhydra/plugins/kernel_pfroute/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libhydra
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-kernel-pfroute.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-kernel-pfroute.la
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
index 63c38bb..c4e8664 100644
--- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
+++ b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -1612,7 +1612,7 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
 }
 
 METHOD(kernel_net_t, get_nexthop, host_t*,
-	private_kernel_pfroute_net_t *this, host_t *dest, host_t *src)
+	private_kernel_pfroute_net_t *this, host_t *dest, int prefix, host_t *src)
 {
 	return get_route(this, TRUE, dest, src);
 }
diff --git a/src/libhydra/plugins/resolve/Makefile.am b/src/libhydra/plugins/resolve/Makefile.am
index 4cbf65f..33c3e70 100644
--- a/src/libhydra/plugins/resolve/Makefile.am
+++ b/src/libhydra/plugins/resolve/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-DRESOLV_CONF=\"${resolv_conf}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-resolve.la
diff --git a/src/libhydra/plugins/resolve/Makefile.in b/src/libhydra/plugins/resolve/Makefile.in
index e76ba57..32eed61 100644
--- a/src/libhydra/plugins/resolve/Makefile.in
+++ b/src/libhydra/plugins/resolve/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-DRESOLV_CONF=\"${resolv_conf}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-resolve.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-resolve.la
diff --git a/src/libimcv/Android.mk b/src/libimcv/Android.mk
new file mode 100644
index 0000000..4253fe2
--- /dev/null
+++ b/src/libimcv/Android.mk
@@ -0,0 +1,66 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+libimcv_la_SOURCES := \
+	imcv.h imcv.c \
+	imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \
+	imc/imc_msg.h imc/imc_msg.c \
+	imc/imc_os_info.h imc/imc_os_info.c \
+	imv/imv_agent.h imv/imv_agent.c imv/imv_state.h \
+	imv/imv_agent_if.h imv/imv_if.h \
+	imv/imv_database.h imv/imv_database.c \
+	imv/imv_msg.h imv/imv_msg.c \
+	imv/imv_lang_string.h imv/imv_lang_string.c \
+	imv/imv_os_info.h imv/imv_os_info.c \
+	imv/imv_reason_string.h imv/imv_reason_string.c \
+	imv/imv_remediation_string.h imv/imv_remediation_string.c \
+	imv/imv_session.h imv/imv_session.c \
+	imv/imv_session_manager.h imv/imv_session_manager.c \
+	imv/imv_workitem.h imv/imv_workitem.c \
+	ietf/ietf_attr.h ietf/ietf_attr.c \
+	ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
+	ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
+	ietf/ietf_attr_fwd_enabled.h ietf/ietf_attr_fwd_enabled.c \
+	ietf/ietf_attr_default_pwd_enabled.h ietf/ietf_attr_default_pwd_enabled.c \
+	ietf/ietf_attr_installed_packages.h ietf/ietf_attr_installed_packages.c \
+	ietf/ietf_attr_numeric_version.h ietf/ietf_attr_numeric_version.c \
+	ietf/ietf_attr_op_status.h ietf/ietf_attr_op_status.c \
+	ietf/ietf_attr_pa_tnc_error.h ietf/ietf_attr_pa_tnc_error.c \
+	ietf/ietf_attr_port_filter.h ietf/ietf_attr_port_filter.c \
+	ietf/ietf_attr_product_info.h ietf/ietf_attr_product_info.c \
+	ietf/ietf_attr_remediation_instr.h ietf/ietf_attr_remediation_instr.c \
+	ietf/ietf_attr_string_version.h ietf/ietf_attr_string_version.c \
+	ita/ita_attr.h ita/ita_attr.c \
+	ita/ita_attr_command.h ita/ita_attr_command.c \
+	ita/ita_attr_dummy.h ita/ita_attr_dummy.c \
+	ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \
+	ita/ita_attr_settings.h ita/ita_attr_settings.c \
+	ita/ita_attr_angel.h ita/ita_attr_angel.c \
+	ita/ita_attr_device_id.h ita/ita_attr_device_id.c \
+	os_info/os_info.h os_info/os_info.c \
+	pa_tnc/pa_tnc_attr.h \
+	pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
+	pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
+
+LOCAL_SRC_FILES := $(filter %.c,$(libimcv_la_SOURCES))
+
+# build libimcv ----------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+	$(strongswan_PATH)/src/libtncif \
+	$(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := libimcv
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan libtncif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am
index 96e7597..4bed3bf 100644
--- a/src/libimcv/Makefile.am
+++ b/src/libimcv/Makefile.am
@@ -11,18 +11,25 @@ libimcv_la_LIBADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libtncif/libtncif.la
 
+if USE_WINDOWS
+  libimcv_la_LIBADD += -lws2_32
+endif
+
 libimcv_la_SOURCES = \
 	imcv.h imcv.c \
 	imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \
 	imc/imc_msg.h imc/imc_msg.c \
+	imc/imc_os_info.h imc/imc_os_info.c \
 	imv/imv_agent.h imv/imv_agent.c imv/imv_state.h \
 	imv/imv_agent_if.h imv/imv_if.h \
 	imv/imv_database.h imv/imv_database.c \
 	imv/imv_msg.h imv/imv_msg.c \
 	imv/imv_lang_string.h imv/imv_lang_string.c \
+	imv/imv_os_info.h imv/imv_os_info.c \
 	imv/imv_reason_string.h imv/imv_reason_string.c \
 	imv/imv_remediation_string.h imv/imv_remediation_string.c \
 	imv/imv_session.h imv/imv_session.c \
+	imv/imv_session_manager.h imv/imv_session_manager.c \
 	imv/imv_workitem.h imv/imv_workitem.c \
 	ietf/ietf_attr.h ietf/ietf_attr.c \
 	ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
@@ -50,10 +57,10 @@ libimcv_la_SOURCES = \
 	pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
 
 ipsec_SCRIPTS = imv/_imv_policy
-EXTRA_DIST = imv/_imv_policy
+EXTRA_DIST = imv/_imv_policy Android.mk
 
 templatesdir = $(pkgdatadir)/templates/database/imv
-dist_templates_DATA = imv/tables.sql imv/data.sql
+dist_templates_DATA = imv/tables.sql imv/tables-mysql.sql imv/data.sql
 
 ipsec_PROGRAMS = imv_policy_manager
 imv_policy_manager_SOURCES = \
diff --git a/src/libimcv/Makefile.in b/src/libimcv/Makefile.in
index 9d8d863..4614dd6 100644
--- a/src/libimcv/Makefile.in
+++ b/src/libimcv/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -81,13 +81,14 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
+ at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
 ipsec_PROGRAMS = imv_policy_manager$(EXEEXT)
- at USE_IMC_TEST_TRUE@am__append_1 = plugins/imc_test
- at USE_IMV_TEST_TRUE@am__append_2 = plugins/imv_test
- at USE_IMC_SCANNER_TRUE@am__append_3 = plugins/imc_scanner
- at USE_IMV_SCANNER_TRUE@am__append_4 = plugins/imv_scanner
- at USE_IMC_OS_TRUE@am__append_5 = plugins/imc_os
- at USE_IMV_OS_TRUE@am__append_6 = plugins/imv_os
+ at USE_IMC_TEST_TRUE@am__append_2 = plugins/imc_test
+ at USE_IMV_TEST_TRUE@am__append_3 = plugins/imv_test
+ at USE_IMC_SCANNER_TRUE@am__append_4 = plugins/imc_scanner
+ at USE_IMV_SCANNER_TRUE@am__append_5 = plugins/imv_scanner
+ at USE_IMC_OS_TRUE@am__append_6 = plugins/imc_os
+ at USE_IMV_OS_TRUE@am__append_7 = plugins/imv_os
 subdir = src/libimcv
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp $(dist_templates_DATA)
@@ -138,14 +139,16 @@ am__uninstall_files_from_dir = { \
 am__installdirs = "$(DESTDIR)$(ipseclibdir)" "$(DESTDIR)$(ipsecdir)" \
 	"$(DESTDIR)$(ipsecdir)" "$(DESTDIR)$(templatesdir)"
 LTLIBRARIES = $(ipseclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
 libimcv_la_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libtncif/libtncif.la
+	$(top_builddir)/src/libtncif/libtncif.la $(am__DEPENDENCIES_1)
 am__dirstamp = $(am__leading_dot)dirstamp
 am_libimcv_la_OBJECTS = imcv.lo imc/imc_agent.lo imc/imc_msg.lo \
-	imv/imv_agent.lo imv/imv_database.lo imv/imv_msg.lo \
-	imv/imv_lang_string.lo imv/imv_reason_string.lo \
-	imv/imv_remediation_string.lo imv/imv_session.lo \
+	imc/imc_os_info.lo imv/imv_agent.lo imv/imv_database.lo \
+	imv/imv_msg.lo imv/imv_lang_string.lo imv/imv_os_info.lo \
+	imv/imv_reason_string.lo imv/imv_remediation_string.lo \
+	imv/imv_session.lo imv/imv_session_manager.lo \
 	imv/imv_workitem.lo ietf/ietf_attr.lo \
 	ietf/ietf_attr_assess_result.lo ietf/ietf_attr_attr_request.lo \
 	ietf/ietf_attr_fwd_enabled.lo \
@@ -343,6 +346,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -361,6 +365,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -388,6 +393,7 @@ 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@
@@ -479,6 +485,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -497,22 +504,24 @@ ipseclib_LTLIBRARIES = libimcv.la
 libimcv_la_LDFLAGS = \
 	-no-undefined
 
-libimcv_la_LIBADD = \
+libimcv_la_LIBADD =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libtncif/libtncif.la
-
+	$(top_builddir)/src/libtncif/libtncif.la $(am__append_1)
 libimcv_la_SOURCES = \
 	imcv.h imcv.c \
 	imc/imc_agent.h imc/imc_agent.c imc/imc_state.h \
 	imc/imc_msg.h imc/imc_msg.c \
+	imc/imc_os_info.h imc/imc_os_info.c \
 	imv/imv_agent.h imv/imv_agent.c imv/imv_state.h \
 	imv/imv_agent_if.h imv/imv_if.h \
 	imv/imv_database.h imv/imv_database.c \
 	imv/imv_msg.h imv/imv_msg.c \
 	imv/imv_lang_string.h imv/imv_lang_string.c \
+	imv/imv_os_info.h imv/imv_os_info.c \
 	imv/imv_reason_string.h imv/imv_reason_string.c \
 	imv/imv_remediation_string.h imv/imv_remediation_string.c \
 	imv/imv_session.h imv/imv_session.c \
+	imv/imv_session_manager.h imv/imv_session_manager.c \
 	imv/imv_workitem.h imv/imv_workitem.c \
 	ietf/ietf_attr.h ietf/ietf_attr.c \
 	ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
@@ -540,9 +549,9 @@ libimcv_la_SOURCES = \
 	pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
 
 ipsec_SCRIPTS = imv/_imv_policy
-EXTRA_DIST = imv/_imv_policy
+EXTRA_DIST = imv/_imv_policy Android.mk
 templatesdir = $(pkgdatadir)/templates/database/imv
-dist_templates_DATA = imv/tables.sql imv/data.sql
+dist_templates_DATA = imv/tables.sql imv/tables-mysql.sql imv/data.sql
 imv_policy_manager_SOURCES = \
 	imv/imv_policy_manager.c \
 	imv/imv_policy_manager_usage.h imv/imv_policy_manager_usage.c
@@ -551,8 +560,8 @@ imv_policy_manager_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la
 
 #imv/imv_policy_manager.o :	$(top_builddir)/config.status
-SUBDIRS = . $(am__append_1) $(am__append_2) $(am__append_3) \
-	$(am__append_4) $(am__append_5) $(am__append_6)
+SUBDIRS = . $(am__append_2) $(am__append_3) $(am__append_4) \
+	$(am__append_5) $(am__append_6) $(am__append_7)
 all: all-recursive
 
 .SUFFIXES:
@@ -630,6 +639,7 @@ imc/$(DEPDIR)/$(am__dirstamp):
 	@: > imc/$(DEPDIR)/$(am__dirstamp)
 imc/imc_agent.lo: imc/$(am__dirstamp) imc/$(DEPDIR)/$(am__dirstamp)
 imc/imc_msg.lo: imc/$(am__dirstamp) imc/$(DEPDIR)/$(am__dirstamp)
+imc/imc_os_info.lo: imc/$(am__dirstamp) imc/$(DEPDIR)/$(am__dirstamp)
 imv/$(am__dirstamp):
 	@$(MKDIR_P) imv
 	@: > imv/$(am__dirstamp)
@@ -641,11 +651,14 @@ imv/imv_database.lo: imv/$(am__dirstamp) imv/$(DEPDIR)/$(am__dirstamp)
 imv/imv_msg.lo: imv/$(am__dirstamp) imv/$(DEPDIR)/$(am__dirstamp)
 imv/imv_lang_string.lo: imv/$(am__dirstamp) \
 	imv/$(DEPDIR)/$(am__dirstamp)
+imv/imv_os_info.lo: imv/$(am__dirstamp) imv/$(DEPDIR)/$(am__dirstamp)
 imv/imv_reason_string.lo: imv/$(am__dirstamp) \
 	imv/$(DEPDIR)/$(am__dirstamp)
 imv/imv_remediation_string.lo: imv/$(am__dirstamp) \
 	imv/$(DEPDIR)/$(am__dirstamp)
 imv/imv_session.lo: imv/$(am__dirstamp) imv/$(DEPDIR)/$(am__dirstamp)
+imv/imv_session_manager.lo: imv/$(am__dirstamp) \
+	imv/$(DEPDIR)/$(am__dirstamp)
 imv/imv_workitem.lo: imv/$(am__dirstamp) imv/$(DEPDIR)/$(am__dirstamp)
 ietf/$(am__dirstamp):
 	@$(MKDIR_P) ietf
@@ -845,15 +858,18 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ietf/$(DEPDIR)/ietf_attr_string_version.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imc/$(DEPDIR)/imc_agent.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imc/$(DEPDIR)/imc_msg.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at imc/$(DEPDIR)/imc_os_info.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_agent.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_database.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_lang_string.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_msg.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_os_info.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_policy_manager.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_policy_manager_usage.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_reason_string.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_remediation_string.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_session.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_session_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at imv/$(DEPDIR)/imv_workitem.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ita/$(DEPDIR)/ita_attr.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ita/$(DEPDIR)/ita_attr_angel.Plo at am__quote@
diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.c b/src/libimcv/ietf/ietf_attr_installed_packages.c
index 462805e..f33f643 100644
--- a/src/libimcv/ietf/ietf_attr_installed_packages.c
+++ b/src/libimcv/ietf/ietf_attr_installed_packages.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -41,8 +41,6 @@ typedef struct package_entry_t package_entry_t;
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
-#define INSTALLED_PACKAGES_MIN_SIZE		4
-
 /**
  * Private data of an ietf_attr_installed_packages_t object.
  */
@@ -132,7 +130,7 @@ METHOD(pa_tnc_attr_t, build, void,
 	{
 		return;
 	}
-	writer = bio_writer_create(INSTALLED_PACKAGES_MIN_SIZE);
+	writer = bio_writer_create(IETF_INSTALLED_PACKAGES_MIN_SIZE);
 	writer->write_uint16(writer, 0x0000);
 	writer->write_uint16(writer, this->packages->get_count(this->packages));
 
@@ -160,7 +158,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
 
 	*offset = 0;
 
-	if (this->value.len < INSTALLED_PACKAGES_MIN_SIZE)
+	if (this->value.len < IETF_INSTALLED_PACKAGES_MIN_SIZE)
 	{
 		DBG1(DBG_TNC, "insufficient data for IETF installed packages");
 		return FAILED;
@@ -168,7 +166,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
 	reader = bio_reader_create(this->value);
 	reader->read_uint16(reader, &reserved);
 	reader->read_uint16(reader, &count);
-	*offset = INSTALLED_PACKAGES_MIN_SIZE;
+	*offset = IETF_INSTALLED_PACKAGES_MIN_SIZE;
 
 	while (reader->remaining(reader))
 	{
diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.h b/src/libimcv/ietf/ietf_attr_installed_packages.h
index b79c404..e19d0f4 100644
--- a/src/libimcv/ietf/ietf_attr_installed_packages.h
+++ b/src/libimcv/ietf/ietf_attr_installed_packages.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@ typedef struct ietf_attr_installed_packages_t ietf_attr_installed_packages_t;
 #include "ietf_attr.h"
 #include "pa_tnc/pa_tnc_attr.h"
 
+#define IETF_INSTALLED_PACKAGES_MIN_SIZE	4
 
 /**
  * Class implementing the IETF PA-TNC Installed Packages attribute.
diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c
index 7dc3abd..5331517 100644
--- a/src/libimcv/imc/imc_agent.c
+++ b/src/libimcv/imc/imc_agent.c
@@ -490,7 +490,7 @@ METHOD(imc_agent_t, reserve_additional_ids, TNC_Result,
 		count--;
 
 		/* store the scalar value in the pointer */
-		pointer = (void*)id;
+		pointer = (void*)(uintptr_t)id;
 		this->additional_ids->insert_last(this->additional_ids, pointer);
 		DBG2(DBG_IMC, "IMC %u \"%s\" reserved additional ID %u",
 					  this->id, this->name, id);
@@ -566,4 +566,3 @@ imc_agent_t *imc_agent_create(const char *name,
 
 	return &this->public;
 }
-
diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c
index 1fc3d3b..1cf81c7 100644
--- a/src/libimcv/imc/imc_msg.c
+++ b/src/libimcv/imc/imc_msg.c
@@ -177,11 +177,21 @@ METHOD(imc_msg_t, send_, TNC_Result,
 /**
  * Print a clearly visible assessment header to the log
  */
-static void print_assessment_header(const char *name, TNC_UInt32 id, bool *first)
+static void print_assessment_header(const char *name, TNC_UInt32 dst_id,
+									TNC_UInt32 src_id, bool *first)
 {
 	if (*first)
 	{
-		DBG1(DBG_IMC, "***** assessment of IMC %u \"%s\" *****", id, name);
+		if (src_id == TNC_IMCID_ANY)
+		{
+			DBG1(DBG_IMC, "***** assessment of IMC %u \"%s\" *****",
+						   dst_id, name);
+		}
+		else
+		{
+			DBG1(DBG_IMC, "***** assessment of IMC %u \"%s\" from IMV %u *****",
+						   dst_id, name, src_id);
+		}
 		*first = FALSE;
 	}
 }
@@ -294,7 +304,7 @@ METHOD(imc_msg_t, receive, TNC_Result,
 			this->state->set_result(this->state, target_imc_id, result);
 
 			print_assessment_header(this->agent->get_name(this->agent),
-									target_imc_id, &first);
+									target_imc_id, this->src_id, &first);
 			DBG1(DBG_IMC, "assessment result is '%N'",
 				 TNC_IMV_Evaluation_Result_names, result);
 		}
@@ -309,7 +319,7 @@ METHOD(imc_msg_t, receive, TNC_Result,
 			parameters = attr_cast->get_parameters(attr_cast);
 
 			print_assessment_header(this->agent->get_name(this->agent),
-									target_imc_id, &first);
+									target_imc_id, this->src_id, &first);
 			if (parameters_type.vendor_id == PEN_IETF)
 			{
 				switch (parameters_type.type)
diff --git a/src/libimcv/imc/imc_os_info.c b/src/libimcv/imc/imc_os_info.c
new file mode 100644
index 0000000..b01a14c
--- /dev/null
+++ b/src/libimcv/imc/imc_os_info.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2012-2014 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.
+ */
+
+/* for GetTickCount64, Windows 7 */
+#ifdef WIN32
+# define _WIN32_WINNT 0x0601
+#endif
+
+#include "imc_os_info.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <collections/linked_list.h>
+#include <utils/debug.h>
+
+typedef struct private_imc_os_info_t private_imc_os_info_t;
+
+/**
+ * Private data of an imc_os_info_t object.
+ *
+ */
+struct private_imc_os_info_t {
+
+	/**
+	 * Public imc_os_info_t interface.
+	 */
+	imc_os_info_t public;
+
+	/**
+	 * OS type
+	 */
+	os_type_t type;
+
+	/**
+	 * OS name
+	 */
+	chunk_t name;
+
+	/**
+	 * OS version
+	 */
+	chunk_t version;
+
+};
+
+METHOD(imc_os_info_t, get_type, os_type_t,
+	private_imc_os_info_t *this)
+{
+	return this->type;
+}
+
+METHOD(imc_os_info_t, get_name, chunk_t,
+	private_imc_os_info_t *this)
+{
+	return this->name;
+}
+
+METHOD(imc_os_info_t, get_numeric_version, void,
+	private_imc_os_info_t *this, u_int32_t *major, u_int32_t *minor)
+{
+	u_char *pos;
+
+	if (major)
+	{
+		*major = atol(this->version.ptr);
+	}
+	pos = memchr(this->version.ptr, '.', this->version.len);
+	if (minor)
+	{
+		*minor = pos ? atol(pos + 1) : 0;
+	}
+}
+
+METHOD(imc_os_info_t, get_version, chunk_t,
+	private_imc_os_info_t *this)
+{
+	return this->version;
+}
+
+#ifdef WIN32
+
+METHOD(imc_os_info_t, get_fwd_status, os_fwd_status_t,
+	private_imc_os_info_t *this)
+{
+	return OS_FWD_UNKNOWN;
+}
+
+METHOD(imc_os_info_t, get_uptime, time_t,
+	private_imc_os_info_t *this)
+{
+	return GetTickCount64() / 1000;
+}
+
+METHOD(imc_os_info_t, get_setting, chunk_t,
+	private_imc_os_info_t *this, char *name)
+{
+	return chunk_empty;
+}
+
+METHOD(imc_os_info_t, create_package_enumerator, enumerator_t*,
+	private_imc_os_info_t *this)
+{
+	return NULL;
+}
+
+/**
+ * Determine Windows release
+ */
+static bool extract_platform_info(os_type_t *type, chunk_t *name,
+								  chunk_t *version)
+{
+	OSVERSIONINFOEX osvie;
+	char buf[64];
+
+	memset(&osvie, 0, sizeof(osvie));
+	osvie.dwOSVersionInfoSize = sizeof(osvie);
+
+	if (!GetVersionEx((LPOSVERSIONINFO)&osvie))
+	{
+		return FALSE;
+	}
+	*type = OS_TYPE_WINDOWS;
+	snprintf(buf, sizeof(buf), "Windows %s %s",
+			 osvie.wProductType == VER_NT_WORKSTATION ? "Client" : "Server",
+#ifdef WIN64
+			 "x86_64"
+#else
+			 "x86"
+#endif
+	);
+	*name = chunk_clone(chunk_from_str(buf));
+
+	snprintf(buf, sizeof(buf), "%d.%d.%d (SP %d.%d)",
+			 osvie.dwMajorVersion, osvie.dwMinorVersion, osvie.dwBuildNumber,
+			 osvie.wServicePackMajor, osvie.wServicePackMinor);
+	*version = chunk_clone(chunk_from_str(buf));
+
+	return TRUE;
+}
+
+#else /* !WIN32 */
+
+#include <sys/utsname.h>
+
+METHOD(imc_os_info_t, get_fwd_status, os_fwd_status_t,
+	private_imc_os_info_t *this)
+{
+	const char ip_forward[] = "/proc/sys/net/ipv4/ip_forward";
+	char buf[2];
+	FILE *file;
+
+	os_fwd_status_t fwd_status = OS_FWD_UNKNOWN;
+
+	file = fopen(ip_forward, "r");
+	if (file)
+	{
+		if (fread(buf, 1, 1, file) == 1)
+		{
+			switch (buf[0])
+			{
+				case '0':
+					fwd_status = OS_FWD_DISABLED;
+					break;
+				case '1':
+					fwd_status = OS_FWD_ENABLED;
+					break;
+				default:
+					DBG1(DBG_IMC, "\"%s\" returns invalid value ", ip_forward);
+					break;
+			}
+		}
+		else
+		{
+			DBG1(DBG_IMC, "could not read from \"%s\"", ip_forward);
+		}
+		fclose(file);
+	}
+	else
+	{
+		DBG1(DBG_IMC, "failed to open \"%s\"", ip_forward);
+	}
+
+	return fwd_status;
+}
+
+METHOD(imc_os_info_t, get_uptime, time_t,
+	private_imc_os_info_t *this)
+{
+	const char proc_uptime[] = "/proc/uptime";
+	FILE *file;
+	u_int uptime;
+
+	file = fopen(proc_uptime, "r");
+	if (!file)
+	{
+		DBG1(DBG_IMC, "failed to open \"%s\"", proc_uptime);
+		return 0;
+	}
+	if (fscanf(file, "%u", &uptime) != 1)
+	{
+		DBG1(DBG_IMC, "failed to read file \"%s\"", proc_uptime);
+		uptime = 0;
+	}
+	fclose(file);
+
+	return uptime;
+}
+
+METHOD(imc_os_info_t, get_setting, chunk_t,
+	private_imc_os_info_t *this, char *name)
+{
+	FILE *file;
+	u_char buf[2048];
+	size_t i = 0;
+	chunk_t value;
+
+	if (!strpfx(name, "/etc/") && !strpfx(name, "/proc/") &&
+		!strpfx(name, "/sys/") && !strpfx(name, "/var/"))
+	{
+		/**
+		 * In order to guarantee privacy, only settings from the
+		 * /etc/, /proc/ and /sys/ directories can be retrieved
+		 */
+		DBG1(DBG_IMC, "not allowed to access '%s'", name);
+
+		return chunk_empty;
+	}
+
+	file = fopen(name, "r");
+	if (!file)
+	{
+		DBG1(DBG_IMC, "failed to open '%s'", name);
+
+		return chunk_empty;
+	}
+	while (i < sizeof(buf) && fread(buf + i, 1, 1, file) == 1)
+	{
+		i++;
+	}
+	fclose(file);
+
+	value = chunk_create(buf, i);
+
+	return chunk_clone(value);
+}
+
+typedef struct {
+	/**
+	 * implements enumerator_t
+	 */
+	enumerator_t public;
+
+	/**
+	 * package info pipe stream
+	 */
+	FILE* file;
+
+	/**
+	 * line buffer
+	 */
+	u_char line[512];
+
+} package_enumerator_t;
+
+/**
+ * Implementation of package_enumerator.destroy.
+ */
+static void package_enumerator_destroy(package_enumerator_t *this)
+{
+	pclose(this->file);
+	free(this);
+}
+
+/**
+ * Implementation of package_enumerator.enumerate
+ */
+static bool package_enumerator_enumerate(package_enumerator_t *this, ...)
+{
+	chunk_t *name, *version;
+	u_char *pos;
+	va_list args;
+
+	while (TRUE)
+	{
+		if (!fgets(this->line, sizeof(this->line), this->file))
+		{
+			return FALSE;
+		}
+
+		pos = strchr(this->line, '\t');
+		if (!pos)
+		{
+			return FALSE;
+		}
+		*pos++ = '\0';
+
+		if (!streq(this->line, "install ok installed"))
+		{
+			continue;
+		}
+		va_start(args, this);
+
+		name = va_arg(args, chunk_t*);
+		name->ptr = pos;
+		pos = strchr(pos, '\t');
+		if (!pos)
+		{
+			va_end(args);
+			return FALSE;
+		}
+		name->len = pos++ - name->ptr;
+
+		version = va_arg(args, chunk_t*);
+		version->ptr = pos;
+		version->len = strlen(pos) - 1;
+
+		va_end(args);
+		return TRUE;
+	}
+}
+
+METHOD(imc_os_info_t, create_package_enumerator, enumerator_t*,
+	private_imc_os_info_t *this)
+{
+	FILE *file;
+	const char command[] = "dpkg-query --show --showformat="
+								"'${Status}\t${Package}\t${Version}\n'";
+	package_enumerator_t *enumerator;
+
+	/* Only Debian and Ubuntu package enumeration is currently supported */
+	if (this->type != OS_TYPE_DEBIAN && this->type != OS_TYPE_UBUNTU)
+	{
+		return NULL;
+	}
+
+	/* Open a pipe stream for reading the output of the dpkg-query commmand */
+	file = popen(command, "r");
+	if (!file)
+	{
+		DBG1(DBG_IMC, "failed to run dpkg command");
+		return NULL;
+	}
+
+	/* Create a package enumerator instance */
+	enumerator = malloc_thing(package_enumerator_t);
+	enumerator->public.enumerate = (void*)package_enumerator_enumerate;
+	enumerator->public.destroy = (void*)package_enumerator_destroy;
+	enumerator->file = file;
+
+	return (enumerator_t*)enumerator;
+}
+
+#define RELEASE_LSB		0
+#define RELEASE_DEBIAN	1
+
+/**
+ * Determine Linux distribution version and hardware platform
+ */
+static bool extract_platform_info(os_type_t *type, chunk_t *name,
+								  chunk_t *version)
+{
+	FILE *file;
+	u_char buf[BUF_LEN], *pos = buf;
+	int len = BUF_LEN - 1;
+	os_type_t os_type = OS_TYPE_UNKNOWN;
+	chunk_t os_name = chunk_empty;
+	chunk_t os_version = chunk_empty;
+	char *os_str;
+	struct utsname uninfo;
+	int i;
+
+	/* Linux/Unix distribution release info (from http://linuxmafia.com) */
+	const char* releases[] = {
+		"/etc/lsb-release",           "/etc/debian_version",
+		"/etc/SuSE-release",          "/etc/novell-release",
+		"/etc/sles-release",          "/etc/redhat-release",
+		"/etc/fedora-release",        "/etc/gentoo-release",
+		"/etc/slackware-version",     "/etc/annvix-release",
+		"/etc/arch-release",          "/etc/arklinux-release",
+		"/etc/aurox-release",         "/etc/blackcat-release",
+		"/etc/cobalt-release",        "/etc/conectiva-release",
+		"/etc/debian_release",        "/etc/immunix-release",
+		"/etc/lfs-release",           "/etc/linuxppc-release",
+		"/etc/mandrake-release",      "/etc/mandriva-release",
+		"/etc/mandrakelinux-release", "/etc/mklinux-release",
+		"/etc/pld-release",           "/etc/redhat_version",
+		"/etc/slackware-release",     "/etc/e-smith-release",
+		"/etc/release",               "/etc/sun-release",
+		"/etc/tinysofa-release",      "/etc/turbolinux-release",
+		"/etc/ultrapenguin-release",  "/etc/UnitedLinux-release",
+		"/etc/va-release",            "/etc/yellowdog-release"
+	};
+
+	const char lsb_distrib_id[]      = "DISTRIB_ID=";
+	const char lsb_distrib_release[] = "DISTRIB_RELEASE=";
+
+	for (i = 0; i < countof(releases); i++)
+	{
+		file = fopen(releases[i], "r");
+		if (!file)
+		{
+			continue;
+		}
+
+		/* read release file into buffer */
+		fseek(file, 0, SEEK_END);
+		len = min(ftell(file), 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;
+		}
+		fclose(file);
+
+		DBG1(DBG_IMC, "processing \"%s\" file", releases[i]);
+
+		switch (i)
+		{
+			case RELEASE_LSB:
+			{
+				/* Determine Distribution ID */
+				pos = strstr(buf, lsb_distrib_id);
+				if (!pos)
+				{
+					DBG1(DBG_IMC, "failed to find begin of DISTRIB_ID field");
+					return FALSE;
+				}
+				pos += strlen(lsb_distrib_id);
+
+				os_name.ptr = pos;
+
+				pos = strchr(pos, '\n');
+				if (!pos)
+				{
+					DBG1(DBG_IMC, "failed to find end of DISTRIB_ID field");
+					return FALSE;
+			 	}
+				os_name.len = pos - os_name.ptr;
+
+				/* Determine Distribution Release */
+				pos = strstr(buf, lsb_distrib_release);
+				if (!pos)
+				{
+					DBG1(DBG_IMC, "failed to find begin of DISTRIB_RELEASE field");
+					return FALSE;
+				}
+				pos += strlen(lsb_distrib_release);
+
+				os_version.ptr = pos;
+
+				pos = strchr(pos, '\n');
+				if (!pos)
+				{
+					DBG1(DBG_IMC, "failed to find end of DISTRIB_RELEASE field");
+					return FALSE;
+			 	}
+				os_version.len = pos - os_version.ptr;
+
+				break;
+			}
+			case RELEASE_DEBIAN:
+			{
+				os_type = OS_TYPE_DEBIAN;
+
+				os_version.ptr = buf;
+				pos = strchr(buf, '\n');
+				if (!pos)
+				{
+					DBG1(DBG_PTS, "failed to find end of release string");
+					return FALSE;
+				}
+
+				os_version.len = pos - os_version.ptr;
+
+				break;
+			}
+			default:
+			{
+				const char str_release[] = " release ";
+
+				os_name.ptr = buf;
+
+				pos = strstr(buf, str_release);
+				if (!pos)
+				{
+					DBG1(DBG_IMC, "failed to find release keyword");
+					return FALSE;
+				}
+
+				os_name.len = pos - os_name.ptr;
+
+				pos += strlen(str_release);
+				os_version.ptr = pos;
+
+				pos = strchr(pos, '\n');
+				if (!pos)
+				{
+					DBG1(DBG_IMC, "failed to find end of release string");
+					return FALSE;
+			 	}
+
+				os_version.len = pos - os_version.ptr;
+
+				break;
+			}
+		}
+		break;
+	}
+
+	if (!os_version.ptr)
+	{
+		DBG1(DBG_IMC, "no distribution release file found");
+		return FALSE;
+	}
+
+	if (uname(&uninfo) < 0)
+	{
+		DBG1(DBG_IMC, "could not retrieve machine architecture");
+		return FALSE;
+	}
+
+	/* Try to find a matching OS type based on the OS name */
+	if (os_type == OS_TYPE_UNKNOWN)
+	{
+		os_type = os_type_from_name(os_name);
+	}
+
+	/* If known use the official OS name */
+	if (os_type != OS_TYPE_UNKNOWN)
+	{
+		os_str = enum_to_name(os_type_names, os_type);
+		os_name = chunk_create(os_str, strlen(os_str));
+	}
+
+	/* copy OS type */
+	*type = os_type;
+
+	/* copy OS name */
+	*name = chunk_clone(os_name);
+
+	/* copy OS version and machine architecture */
+	*version = chunk_alloc(os_version.len + 1 + strlen(uninfo.machine));
+	pos = version->ptr;
+	memcpy(pos, os_version.ptr, os_version.len);
+	pos += os_version.len;
+	*pos++ = ' ';
+	memcpy(pos, uninfo.machine, strlen(uninfo.machine));
+
+	return TRUE;
+}
+
+#endif /* !WIN32 */
+
+METHOD(imc_os_info_t, destroy, void,
+	private_imc_os_info_t *this)
+{
+	free(this->name.ptr);
+	free(this->version.ptr);
+	free(this);
+}
+
+/**
+ * See header
+ */
+imc_os_info_t *imc_os_info_create(void)
+{
+	private_imc_os_info_t *this;
+	chunk_t name, version;
+	os_type_t type;
+
+	/* As an option OS name and OS version can be configured manually */
+	name.ptr = lib->settings->get_str(lib->settings,
+									  "%s.imcv.imc_os_info.name", NULL, lib->ns);
+	version.ptr = lib->settings->get_str(lib->settings,
+									  "%s.imcv.imc_os_info.version", NULL, lib->ns);
+	if (name.ptr && version.ptr)
+	{
+		name.len = strlen(name.ptr);
+		name = chunk_clone(name);
+
+		version.len = strlen(version.ptr);
+		version = chunk_clone(version);
+
+		type = os_type_from_name(name);
+	}
+	else
+	{
+		if (!extract_platform_info(&type, &name, &version))
+		{
+			return NULL;
+		}
+	}
+	DBG1(DBG_IMC, "operating system name is '%.*s'",
+				   name.len, name.ptr);
+	DBG1(DBG_IMC, "operating system version is '%.*s'",
+				   version.len, version.ptr);
+
+	INIT(this,
+		.public = {
+			.get_type = _get_type,
+			.get_name = _get_name,
+			.get_numeric_version = _get_numeric_version,
+			.get_version = _get_version,
+			.get_fwd_status = _get_fwd_status,
+			.get_uptime = _get_uptime,
+			.get_setting = _get_setting,
+			.create_package_enumerator = _create_package_enumerator,
+			.destroy = _destroy,
+		},
+		.type = type,
+		.name = name,
+		.version = version,
+	);
+
+	return &this->public;
+}
diff --git a/src/libimcv/imc/imc_os_info.h b/src/libimcv/imc/imc_os_info.h
new file mode 100644
index 0000000..a6db443
--- /dev/null
+++ b/src/libimcv/imc/imc_os_info.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012-2014 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 imc_os_info imc_os_info
+ * @{ @ingroup libimcv
+ */
+
+#ifndef IMC_OS_INFO_H_
+#define IMC_OS_INFO_H_
+
+typedef struct imc_os_info_t imc_os_info_t;
+
+#include "os_info/os_info.h"
+
+#include <library.h>
+
+#include <time.h>
+
+/**
+ * Interface for the IMC Operating System (OS) information module
+ */
+struct imc_os_info_t {
+
+	/**
+	 * Get the OS type if it can be determined
+	 *
+	 * @return					OS type
+	 */
+	os_type_t (*get_type)(imc_os_info_t *this);
+
+	/**
+	 * Get the OS product name or distribution
+	 *
+	 * @return					OS name
+	 */
+	chunk_t (*get_name)(imc_os_info_t *this);
+
+	/**
+	 * Get the numeric OS version or release
+	 *
+	 * @param major				OS major version number
+	 * @param minor				OS minor version number
+	 */
+	void (*get_numeric_version)(imc_os_info_t *this, u_int32_t *major,
+												 u_int32_t *minor);
+
+	/**
+	 * Get the OS version or release
+	 *
+	 * @return					OS version
+	 */
+	chunk_t (*get_version)(imc_os_info_t *this);
+
+	/**
+	 * Get the OS IPv4 forwarding status
+	 *
+	 * @return					IP forwarding status
+	 */
+	os_fwd_status_t (*get_fwd_status)(imc_os_info_t *this);
+
+	/**
+	 * Get the OS uptime in seconds
+	 *
+	 * @return					OS uptime
+	 */
+	time_t (*get_uptime)(imc_os_info_t *this);
+
+	/**
+	 * Get an OS setting (restricted to /proc, /sys, and /etc)
+	 *
+	 * @param name				name of OS setting
+	 * @return					value of OS setting
+	 */
+	chunk_t (*get_setting)(imc_os_info_t *this, char *name);
+
+	/**
+	 * Enumerates over all installed packages
+	 *
+	 * @return				return package enumerator
+	 */
+	enumerator_t* (*create_package_enumerator)(imc_os_info_t *this);
+
+	/**
+	 * Destroys an imc_os_info_t object.
+	 */
+	void (*destroy)(imc_os_info_t *this);
+};
+
+/**
+ * Create an imc_os_info_t object
+ */
+imc_os_info_t* imc_os_info_create(void);
+
+#endif /** IMC_OS_INFO_H_ @}*/
diff --git a/src/libimcv/imcv.c b/src/libimcv/imcv.c
index 2a4fd33..30679a3 100644
--- a/src/libimcv/imcv.c
+++ b/src/libimcv/imcv.c
@@ -20,7 +20,9 @@
 #include <utils/utils.h>
 #include <pen/pen.h>
 
+#ifdef HAVE_SYSLOG
 #include <syslog.h>
+#endif
 
 #define IMCV_DEBUG_LEVEL			1
 #define IMCV_DEFAULT_POLICY_SCRIPT	"ipsec _imv_policy"
@@ -32,6 +34,11 @@
 pa_tnc_attr_manager_t *imcv_pa_tnc_attributes;
 
 /**
+ * Global list of IMV sessions
+ */
+imv_session_manager_t *imcv_sessions;
+
+/**
  * Global IMV database
  */
 imv_database_t *imcv_db;
@@ -57,9 +64,6 @@ static bool imcv_stderr_quiet;
  */
 static void imcv_dbg(debug_t group, level_t level, char *fmt, ...)
 {
-	int priority = LOG_INFO;
-	char buffer[8192];
-	char *current = buffer, *next;
 	va_list args;
 
 	if (level <= imcv_debug_level)
@@ -73,22 +77,30 @@ static void imcv_dbg(debug_t group, level_t level, char *fmt, ...)
 			va_end(args);
 		}
 
-		/* write in memory buffer first */
-		va_start(args, fmt);
-		vsnprintf(buffer, sizeof(buffer), fmt, args);
-		va_end(args);
-
-		/* do a syslog with every line */
-		while (current)
+#ifdef HAVE_SYSLOG
 		{
-			next = strchr(current, '\n');
-			if (next)
+			int priority = LOG_INFO;
+			char buffer[8192];
+			char *current = buffer, *next;
+
+			/* write in memory buffer first */
+			va_start(args, fmt);
+			vsnprintf(buffer, sizeof(buffer), fmt, args);
+			va_end(args);
+
+			/* do a syslog with every line */
+			while (current)
 			{
-				*(next++) = '\0';
+				next = strchr(current, '\n');
+				if (next)
+				{
+					*(next++) = '\0';
+				}
+				syslog(priority, "[HSR] %s\n", current);
+				current = next;
 			}
-			syslog(priority, "[HSR] %s\n", current);
-			current = next;
 		}
+#endif /* HAVE_SYSLOG */
 	}
 }
 
@@ -122,7 +134,9 @@ bool libimcv_init(bool is_imv)
 
 		/* activate the imcv debugging hook */
 		dbg = imcv_dbg;
+#ifdef HAVE_SYSLOG
 		openlog("imcv", 0, LOG_DAEMON);
+#endif
 
 		if (!lib->plugins->load(lib->plugins,
 				lib->settings->get_str(lib->settings, "libimcv.load",
@@ -149,9 +163,12 @@ bool libimcv_init(bool is_imv)
 		imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_ITA,
 							ita_attr_create_from_data, ita_attr_names);
 
-		/* attach global IMV database */
 		if (is_imv)
 		{
+			/* instantiate global IMV session manager */
+			imcv_sessions = imv_session_manager_create();
+
+			/* instantiate and attach global IMV database if URI is valid */
 			uri = lib->settings->get_str(lib->settings,
 						"%s.imcv.database", NULL, lib->ns);
 			script = lib->settings->get_str(lib->settings,
@@ -181,6 +198,7 @@ void libimcv_deinit(void)
 		DESTROY_IF(imcv_pa_tnc_attributes);
 		imcv_pa_tnc_attributes = NULL;
 		DESTROY_IF(imcv_db);
+		DESTROY_IF(imcv_sessions);
 		DBG1(DBG_LIB, "libimcv terminated");
 	}
 	if (ref_put(&libstrongswan_ref))
@@ -188,4 +206,3 @@ void libimcv_deinit(void)
 		library_deinit();
 	}
 }
-
diff --git a/src/libimcv/imcv.h b/src/libimcv/imcv.h
index 10c66e6..7710388 100644
--- a/src/libimcv/imcv.h
+++ b/src/libimcv/imcv.h
@@ -36,6 +36,7 @@
 
 #include "pa_tnc/pa_tnc_attr_manager.h"
 #include "imv/imv_database.h"
+#include "imv/imv_session_manager.h"
 
 #include <library.h>
 
@@ -62,4 +63,9 @@ extern pa_tnc_attr_manager_t* imcv_pa_tnc_attributes;
  */
 extern imv_database_t* imcv_db;
 
+/**
+ * Global IMV session manager
+ */
+extern imv_session_manager_t* imcv_sessions;
+
 #endif /** IMCV_H_ @}*/
diff --git a/src/libimcv/imv/_imv_policy b/src/libimcv/imv/_imv_policy
index 68a963c..0562844 100755
--- a/src/libimcv/imv/_imv_policy
+++ b/src/libimcv/imv/_imv_policy
@@ -20,18 +20,20 @@
 # that, and use the "libimcv.policy_script = " option in strongswan.conf
 # to make strongSwan use yours instead of this default one.
 
-# Environment variables that this script gets 
+# Passed arguments
 #
-#    TNC_SESSION_ID 
-#         unique session ID used as a reference by the policy 
-#         manager. 
+#    $1
+#         action
+#    $2
+#         unique session ID used as a reference by the policy
+#         manager.
 #
 case "$1" in
 start)
-	echo "start session $TNC_SESSION_ID"
+	echo "start session $2"
 	;;
 stop)
-	echo "stop session $TNC_SESSION_ID"
+	echo "stop session $2"
 	;;
 *)	echo "$0: unknown command '$1'"
 	exit 1
diff --git a/src/libimcv/imv/data.sql b/src/libimcv/imv/data.sql
index 7f3bae8..b45cad4 100644
--- a/src/libimcv/imv/data.sql
+++ b/src/libimcv/imv/data.sql
@@ -216,6 +216,96 @@ INSERT INTO products (			/* 36 */
  'Ubuntu 14.04 x86_64'
 );
 
+INSERT INTO products (			/* 37 */
+  name
+) VALUES (
+ 'Debian 7.3 i686'
+);
+
+INSERT INTO products (			/* 38 */
+  name
+) VALUES (
+ 'Debian 7.3 x86_64'
+);
+
+INSERT INTO products (			/* 39 */
+  name
+) VALUES (
+ 'Debian 7.4 i686'
+);
+
+INSERT INTO products (			/* 40 */
+  name
+) VALUES (
+ 'Debian 7.4 x86_64'
+);
+
+INSERT INTO products (			/* 41 */
+  name
+) VALUES (
+ 'Debian 7.5 i686'
+);
+
+INSERT INTO products (			/* 42 */
+  name
+) VALUES (
+ 'Debian 7.5 x86_64'
+);
+
+INSERT INTO products (			/* 43 */
+  name
+) VALUES (
+ 'Debian 7.0 armv6l'
+);
+
+INSERT INTO products (			/* 44 */
+  name
+) VALUES (
+ 'Debian 7.1 armv6l'
+);
+
+INSERT INTO products (			/* 45 */
+  name
+) VALUES (
+ 'Debian 7.2 armv6l'
+);
+
+INSERT INTO products (			/* 46 */
+  name
+) VALUES (
+ 'Debian 7.3 armv6l'
+);
+
+INSERT INTO products (			/* 47 */
+  name
+) VALUES (
+ 'Debian 7.4 armv6l'
+);
+
+INSERT INTO products (			/* 48 */
+  name
+) VALUES (
+ 'Debian 7.5 armv6l'
+);
+
+INSERT INTO products (			/* 49 */
+  name
+) VALUES (
+ 'Android 4.3'
+);
+
+INSERT INTO products (			/* 50 */
+  name
+) VALUES (
+ 'Android 4.4.3'
+);
+
+INSERT INTO products (			/* 51 */
+  name
+) VALUES (
+ 'Android 4.4.4'
+);
+
 /* Directories */
 
 INSERT INTO directories (		/*  1 */
@@ -345,12 +435,6 @@ INSERT INTO files (				/*  6 */
 INSERT INTO algorithms (
   id, name
 ) VALUES (
-  65536, 'SHA1-IMA' 
-);
-
-INSERT INTO algorithms (
-  id, name
-) VALUES (
   32768, 'SHA1' 
 );
 
@@ -531,27 +615,27 @@ INSERT INTO versions (
 /* Components */
 
 INSERT INTO components (
-  vendor_id, name, qualifier
+  vendor_id, name, qualifier, label
 ) VALUES (
-  36906, 1, 33  /* ITA TGRUB */
+  36906, 1, 33, 'G'  /* ITA TGRUB */
 );
 
 INSERT INTO components (
-  vendor_id, name, qualifier
+  vendor_id, name, qualifier, label
 ) VALUES (
-  36906, 2, 33  /* ITA TBOOT */
+  36906, 2, 33, 'T'  /* ITA TBOOT */
 );
 
 INSERT INTO components (
-  vendor_id, name, qualifier
+  vendor_id, name, qualifier, label
 ) VALUES (
-  36906, 3, 33  /* ITA IMA - Trusted Platform */
+  36906, 3, 33, 'B' /* ITA IMA - Trusted Platform */
 );
 
 INSERT INTO components (
-  vendor_id, name, qualifier
+  vendor_id, name, qualifier, label
 ) VALUES (
-  36906, 3, 34  /* ITA IMA - Operating System */
+  36906, 3, 34, 'I' /* ITA IMA - Operating System */
 );
 
 /* Groups */
@@ -634,6 +718,12 @@ INSERT INTO groups (            /* 13 */
   'TPM BIOS/IMA'
 );
 
+INSERT INTO groups (			/* 14 */
+  name, parent
+) VALUES (
+  'Debian armv6l', 2
+);
+
 /* Default Product Groups */
 
 INSERT INTO groups_product_defaults (
@@ -669,6 +759,24 @@ INSERT INTO groups_product_defaults (
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
+  4, 37
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  4, 39
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  4, 41
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
   5, 2
 );
 
@@ -699,6 +807,24 @@ INSERT INTO groups_product_defaults (
 INSERT INTO groups_product_defaults (
   group_id, product_id
 ) VALUES (
+  5, 38
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  5, 40
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  5, 42
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
   6, 9
 );
 
@@ -846,6 +972,60 @@ INSERT INTO groups_product_defaults (
   3, 34
 );
 
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  3, 49
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  3, 50
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  3, 51
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  14, 43
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  14, 44
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  14, 45
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  14, 46
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  14, 47
+);
+
+INSERT INTO groups_product_defaults (
+  group_id, product_id
+) VALUES (
+  14, 48
+);
+
 /* Policies */
 
 INSERT INTO policies (			/*  1 */
@@ -1078,139 +1258,64 @@ INSERT INTO enforcements (      /* 17 */
   21, 13, 60
 );
 
-/* regids */
+/* swid_entities */
 
-INSERT INTO regids (			/*  1 */
-  name
-) VALUES (
- 'regid.1986-12.com.adobe'
-);
-
-INSERT INTO regids (			/*  2 */
-  name
-) VALUES (
- 'regid.1991-06.com.microsoft'
-);
-
-INSERT INTO regids (			/*  3 */
-  name
-) VALUES (
- 'regid.2004-05.com.ubuntu'
-);
-
-INSERT INTO regids (			/*  4 */
-  name
-) VALUES (
- 'regid.1995-04.org.apache'
-);
-
-INSERT INTO regids (			/*  5 */
-  name
-) VALUES (
- 'regid.1999-03.org.debian'
-);
-
-INSERT INTO regids (			/*  6 */
-  name
-) VALUES (
- 'regid.1994-04.org.isc'
-);
-
-INSERT INTO regids (			/*  7 */
-  name
-) VALUES (
- 'regid.1998-12.org.openssl'
-);
-
-INSERT INTO regids (			/*  8 */
-  name
-) VALUES (
- 'regid.1998-01.org.samba'
-);
-
-INSERT INTO regids (			/*  9 */
-  name
-) VALUES (
- 'regid.2002-08.org.sqlite'
-);
-
-INSERT INTO regids (			/* 10 */
-  name
-) VALUES (
- 'regid.2004-03.org.strongswan'
-);
-
-/* Tags */
-
-INSERT INTO tags (
-  regid, unique_sw_id
-) VALUES (
-  2, 'Windows-8-Pro'
-);
-
-INSERT INTO tags (
-  regid, unique_sw_id
-) VALUES (
-  5, 'apache-2-2-22-13'
-);
-
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO "swid_entities" (		/*  1 */
+  "name", "regid"
 ) VALUES (
-  5, 'bind-9-8-4-dfsg'
+  'strongSwan Project', 'regid.2004-03.org.strongswan'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  2 */
+  "name", "regid"
 ) VALUES (
-  5, 'libsqlite-3-7-13-1'
+  'Adobe Systems Inc.', 'regid.1986-12.com.adobe'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  3 */
+  "name", "regid"
 ) VALUES (
-  5, 'libssl-1-0-1e-2'
+  'Microsoft Corporation', 'regid.1991-06.com.microsoft'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  4 */
+  "name", "regid"
 ) VALUES (
-  5, 'libssl-dev-1-0-1e-2'
+  'Ubuntu Project', 'regid.2004-05.com.ubuntu'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  5 */
+  "name", "regid"
 ) VALUES (
-  5, 'libssl-doc-1-0-1e-2'
+  'Apache Software Foundation', 'regid.1995-04.org.apache'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  6 */
+  "name", "regid"
 ) VALUES (
-  5, 'openssl-1-0-1e-2'
+  'Debian Project', 'regid.1999-03.org.debian'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  7 */
+  "name", "regid"
 ) VALUES (
-  5, 'smbclient-3-6-6-6'
+  'Internet Systems Consortium', 'regid.1994-04.org.isc'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  8 */
+  "name", "regid"
 ) VALUES (
-  5, 'sqlite-3-7-13-1'
+  'OpenSSL Project', 'regid.1998-12.org.openssl'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/*  9 */
+  "name", "regid"
 ) VALUES (
-  10, 'strongSwan-5-1-1'
+  'Samba Project', 'regid.1998-01.org.samba'
 );
 
-INSERT INTO tags (
-  regid, unique_sw_id
+INSERT INTO swid_entities (			/* 10 */
+  "name", "regid"
 ) VALUES (
-  10, 'strongSwan-5-1-2'
+  'SQLite Project', 'regid.2002-08.org.sqlite'
 );
-
diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c
index 435c25a..a46455d 100644
--- a/src/libimcv/imv/imv_agent.c
+++ b/src/libimcv/imv/imv_agent.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@ struct private_imv_agent_t {
 	/**
 	 * number of message types registered by IMV
 	 */
-	u_int32_t type_count;
+	uint32_t type_count;
 
 	/**
 	 * ID of IMV as assigned by TNCS
@@ -296,10 +296,7 @@ static bool delete_connection(private_imv_agent_t *this, TNC_ConnectionID id)
 		{
 			found = TRUE;
 			session = state->get_session(state);
-			if (session)
-			{
-				imcv_db->remove_session(imcv_db, session);
-			}
+			imcv_sessions->remove_session(imcv_sessions, session);
 			state->destroy(state);
 			this->connections->remove_at(this->connections, enumerator);
 			break;
@@ -346,7 +343,7 @@ static char* get_str_attribute(private_imv_agent_t *this, TNC_ConnectionID id,
 /**
  * Read an UInt32 attribute
  */
-static u_int32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID id,
+static uint32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID id,
 									TNC_AttributeID attribute_id)
 {
 	TNC_UInt32 len;
@@ -370,7 +367,7 @@ static linked_list_t* get_identity_attribute(private_imv_agent_t *this,
 {
 	TNC_UInt32 len;
 	char buf[2048];
-	u_int32_t count;
+	uint32_t count;
 	tncif_identity_t *tnc_id;
 	bio_reader_t *reader;
 	linked_list_t *list;
@@ -415,8 +412,8 @@ METHOD(imv_agent_t, create_state, TNC_Result,
 	enumerator_t *enumerator;
 	tncif_identity_t *tnc_id;
 	imv_session_t *session;
-	u_int32_t max_msg_len;
-	u_int32_t ar_id_type = TNC_ID_UNKNOWN;
+	uint32_t max_msg_len;
+	uint32_t ar_id_type = TNC_ID_UNKNOWN;
 	chunk_t ar_id_value = chunk_empty;
 
 	conn_id = state->get_connection_id(state);
@@ -453,7 +450,7 @@ METHOD(imv_agent_t, create_state, TNC_Result,
 	while (enumerator->enumerate(enumerator, &tnc_id))
 	{
 		pen_type_t id_type, subject_type, auth_type;
-		u_int32_t tcg_id_type, tcg_subject_type, tcg_auth_type;
+		uint32_t tcg_id_type, tcg_subject_type, tcg_auth_type;
 		chunk_t id_value;
 
 		id_type = tnc_id->get_identity_type(tnc_id);
@@ -474,30 +471,21 @@ METHOD(imv_agent_t, create_state, TNC_Result,
 			 id_value.len, id_value.ptr,
 			 TNC_Authentication_names, tcg_auth_type);
 
+		/* keep the first access requestor ID */
 		if (first)
 		{
 			ar_id_type = tcg_id_type;
 			ar_id_value = id_value;
-			state->set_ar_id(state, ar_id_type, ar_id_value);
 			first = FALSE;
 		}
 	}
 	enumerator->destroy(enumerator);
 
-	if (imcv_db)
-	{
-		session = imcv_db->add_session(imcv_db, conn_id, ar_id_type, ar_id_value);
-		if (session)
-		{
-			DBG2(DBG_IMV, "  assigned session ID %d",
-				 session->get_session_id(session));
-			state->set_session(state, session);
-		}
-		else
-		{
-			DBG1(DBG_IMV, "  no session ID assigned");
-		}
-	}
+	session = imcv_sessions->add_session(imcv_sessions, conn_id,
+										 ar_id_type, ar_id_value);
+	state->set_session(state, session);
+
+	/* clean up temporary variables */
 	ar_identities->destroy_offset(ar_identities,
 						   offsetof(tncif_identity_t, destroy));
 	free(tnccs_p);
@@ -505,9 +493,11 @@ METHOD(imv_agent_t, create_state, TNC_Result,
 	free(t_p);
 	free(t_v);
 
+	/* insert state in connection list */
 	this->connection_lock->write_lock(this->connection_lock);
 	this->connections->insert_last(this->connections, state);
 	this->connection_lock->unlock(this->connection_lock);
+
 	return TNC_RESULT_SUCCESS;
 }
 
@@ -622,7 +612,7 @@ METHOD(imv_agent_t, reserve_additional_ids, TNC_Result,
 		count--;
 
 		/* store the scalar value in the pointer */
-		pointer = (void*)id;
+		pointer = (void*)(uintptr_t)id;
 		this->additional_ids->insert_last(this->additional_ids, pointer);
 		DBG2(DBG_IMV, "IMV %u \"%s\" reserved additional ID %u",
 					  this->id, this->name, id);
@@ -800,7 +790,7 @@ METHOD(imv_agent_t, destroy, void,
  * Described in header.
  */
 imv_agent_t *imv_agent_create(const char *name,
-							  pen_type_t *supported_types, u_int32_t type_count,
+							  pen_type_t *supported_types, uint32_t type_count,
 							  TNC_IMVID id, TNC_Version *actual_version)
 {
 	private_imv_agent_t *this;
@@ -841,5 +831,3 @@ imv_agent_t *imv_agent_create(const char *name,
 
 	return &this->public;
 }
-
-
diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h
index d58af26..47ce770 100644
--- a/src/libimcv/imv/imv_agent.h
+++ b/src/libimcv/imv/imv_agent.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -205,7 +205,7 @@ struct imv_agent_t {
  *
  */
 imv_agent_t *imv_agent_create(const char *name,
-							  pen_type_t *supported_types, u_int32_t type_count,
+							  pen_type_t *supported_types, uint32_t type_count,
 							  TNC_IMVID id, TNC_Version *actual_version);
 
 #endif /** IMV_AGENT_H_ @}*/
diff --git a/src/libimcv/imv/imv_database.c b/src/libimcv/imv/imv_database.c
index dc7edd7..0c4bb75 100644
--- a/src/libimcv/imv/imv_database.c
+++ b/src/libimcv/imv/imv_database.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -47,48 +47,28 @@ struct private_imv_database_t {
 	 */
 	char *script;
 
-	/**
-	 * Session list
-	 */
-	linked_list_t *sessions;
-
-	/**
-	 * mutex used to lock session list
-	 */
-	mutex_t *mutex;
-
 };
 
-METHOD(imv_database_t, add_session, imv_session_t*,
-	private_imv_database_t *this, TNC_ConnectionID conn_id,
-	u_int32_t ar_id_type, chunk_t ar_id_value)
+METHOD(imv_database_t, get_database, database_t*,
+	private_imv_database_t *this)
 {
-	enumerator_t *enumerator, *e;
-	imv_session_t *current, *session = NULL;
-	int ar_id = 0, session_id;
-	u_int created;
-
-	this->mutex->lock(this->mutex);
-
-	/* check if a session has already been assigned */
-	enumerator = this->sessions->create_enumerator(this->sessions);
-	while (enumerator->enumerate(enumerator, &current))
-	{
-		if (conn_id == current->get_connection_id(current))
-		{
-			session = current;
-			break;
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	/* session already exists */
-	if (session)
-	{
-		this->mutex->unlock(this->mutex);
-		return session->get_ref(session);
-	}
+	return this->db;
+}
 
+/**
+ * Create a session entry in the IMV database
+ */
+static bool create_session(private_imv_database_t *this, imv_session_t *session)
+{
+	enumerator_t *e;
+	imv_os_info_t *os_info;
+	chunk_t device_id, ar_id_value;
+	TNC_ConnectionID conn_id;
+	uint32_t ar_id_type;
+	char *product, *device;
+	int session_id = 0, ar_id = 0, pid = 0, did = 0, trusted = 0, created;
+
+	ar_id_value = session->get_ar_id(session, &ar_id_type);
 	if (ar_id_value.len)
 	{
 		/* get primary key of AR identity if it exists */
@@ -108,46 +88,22 @@ METHOD(imv_database_t, add_session, imv_session_t*,
 				"INSERT INTO identities (type, value) VALUES (?, ?)",
 				 DB_INT, ar_id_type, DB_BLOB, ar_id_value);
 		}
-	}
-	/* create a new session entry */
-	created = time(NULL);
-	this->db->execute(this->db, &session_id,
-				"INSERT INTO sessions (time, connection, identity) "
-				"VALUES (?, ?, ?)",
-				DB_UINT, created, DB_INT, conn_id, DB_INT, ar_id);
-	session = imv_session_create(session_id, conn_id);
-	this->sessions->insert_last(this->sessions, session);
-
-	this->mutex->unlock(this->mutex);
-
-	return session;
-}
 
-METHOD(imv_database_t, remove_session, void,
-	private_imv_database_t *this, imv_session_t *session)
-{
-	enumerator_t *enumerator;
-	imv_session_t *current;
-
-	this->mutex->lock(this->mutex);
-	enumerator = this->sessions->create_enumerator(this->sessions);
-	while (enumerator->enumerate(enumerator, &current))
-	{
-		if (current == session)
+		if (!ar_id)
 		{
-			this->sessions->remove_at(this->sessions, enumerator);
-			break;
+			DBG1(DBG_IMV, "imv_db: registering access requestor failed");
+			return FALSE;
 		}
 	}
-	enumerator->destroy(enumerator);
-	this->mutex->unlock(this->mutex);
-}
 
-METHOD(imv_database_t, add_product, int,
-	private_imv_database_t *this, imv_session_t *session, char *product)
-{
-	enumerator_t *e;
-	int pid = 0;
+	/* get product info string */
+	os_info = session->get_os_info(session);
+	product = os_info->get_info(os_info);
+	if (!product)
+	{
+		DBG1(DBG_IMV, "imv_db: product info is not available");
+		return FALSE;
+	}
 
 	/* get primary key of product info string if it exists */
 	e = this->db->query(this->db,
@@ -164,92 +120,150 @@ METHOD(imv_database_t, add_product, int,
 		this->db->execute(this->db, &pid,
 			"INSERT INTO products (name) VALUES (?)", DB_TEXT, product);
 	}
-	
-	/* add product reference to session */
-	if (pid)
+
+	if (!pid)
 	{
-		this->db->execute(this->db, NULL,
-			"UPDATE sessions SET product = ? WHERE id = ?",
-			 DB_INT, pid, DB_INT, session->get_session_id(session));
+		DBG1(DBG_IMV, "imv_db: registering product info failed");
+		return FALSE;
 	}
 
-	return pid;
-}
-
-METHOD(imv_database_t, add_device, int,
-	private_imv_database_t *this, imv_session_t *session, chunk_t device)
-{
-	enumerator_t *e;
-	char *device_str;
-	int pid = 0, did = 0;
+	/* get device ID string */
+	if (!session->get_device_id(session, &device_id))
+	{
+		DBG1(DBG_IMV, "imv_db: device ID is not available");
+		return FALSE;
+	}
+	device = strndup(device_id.ptr, device_id.len);
 
-	/* get primary key of product from session */
+	/* get primary key of device ID if it exists */
 	e = this->db->query(this->db,
-			"SELECT product FROM sessions WHERE id = ?",
-			 DB_INT, session->get_session_id(session), DB_INT);
+			"SELECT id, trusted FROM devices WHERE value = ? AND product = ?",
+			 DB_TEXT, device, DB_INT, pid, DB_INT, DB_INT);
 	if (e)
 	{
-		e->enumerate(e, &pid);
+		e->enumerate(e, &did, &trusted);
 		e->destroy(e);
 	}
 
-	/* some IMV policy manager expect a text string */
-	device_str = strndup(device.ptr, device.len);
-
-	/* get primary key of device identification if it exists */
-	e = this->db->query(this->db,
-			"SELECT id FROM devices WHERE value = ? AND product = ?",
-			 DB_TEXT, device_str, DB_INT, pid, DB_INT);
-	if (e)
+	/* if device ID is trusted, set trust in session */
+	if (trusted)
 	{
-		e->enumerate(e, &did);
-		e->destroy(e);
+		session->set_device_trust(session, TRUE);
 	}
 
-	/* if device identification has not been found - register it */
+	/* if device ID has not been found - register it */
 	if (!did)
 	{
 		this->db->execute(this->db, &did,
 			"INSERT INTO devices (value, product) VALUES (?, ?)",
-			 DB_TEXT, device_str, DB_INT, pid);
+			 DB_TEXT, device, DB_INT, pid);
+	}
+	free(device);
+
+	if (!did)
+	{
+		DBG1(DBG_IMV, "imv_db: registering device ID failed");
+		return FALSE;
+	}
+
+	/* create a new session entry */
+	created = session->get_creation_time(session);
+	conn_id = session->get_connection_id(session);
+	this->db->execute(this->db, &session_id,
+			"INSERT INTO sessions (time, connection, identity, product, device) "
+			"VALUES (?, ?, ?, ?, ?)",
+			DB_INT, created, DB_INT, conn_id, DB_INT, ar_id,
+			DB_INT, pid, DB_INT, did);
+
+	if (session_id)
+	{
+		DBG2(DBG_IMV, "assigned session ID %d to Connection ID %d",
+					   session_id, conn_id);
+	}
+	else
+	{
+		DBG1(DBG_IMV, "imv_db: registering session failed");
+		return FALSE;
+	}
+	session->set_session_id(session, session_id, pid, did);
+
+	return TRUE;
+}
+
+static bool add_workitems(private_imv_database_t *this, imv_session_t *session)
+{
+	char *arg_str;
+	int id, arg_int, rec_fail, rec_noresult;
+	imv_workitem_t *workitem;
+	imv_workitem_type_t type;
+	enumerator_t *e;
+
+	e = this->db->query(this->db,
+			"SELECT id, type, arg_str, arg_int, rec_fail, rec_noresult "
+			"FROM workitems WHERE session = ?",
+			 DB_INT, session->get_session_id(session, NULL, NULL),
+			 DB_INT, DB_INT, DB_TEXT, DB_INT,DB_INT, DB_INT);
+	if (!e)
+	{
+		DBG1(DBG_IMV, "imv_db: no workitem enumerator returned");
+		return FALSE;
 	}
-	free(device_str);
-	
-	/* add device reference to session */
-	if (did)
+	while (e->enumerate(e, &id, &type, &arg_str, &arg_int, &rec_fail,
+						   &rec_noresult))
 	{
-		this->db->execute(this->db, NULL,
-			"UPDATE sessions SET device = ? WHERE id = ?",
-			 DB_INT, did, DB_INT, session->get_session_id(session));
+		DBG2(DBG_IMV, "%N workitem %d", imv_workitem_type_names, type, id);
+		workitem = imv_workitem_create(id, type, arg_str, arg_int, rec_fail,
+									   rec_noresult);
+		session->insert_workitem(session, workitem);
 	}
+	e->destroy(e);
 
-	return did;
+	return TRUE;
 }
 
 METHOD(imv_database_t, add_recommendation, void,
 	private_imv_database_t *this, imv_session_t *session,
 	TNC_IMV_Action_Recommendation rec)
 {
-	/* add final recommendation to session */
+	/* add final recommendation to session DB entry */
 	this->db->execute(this->db, NULL,
 			"UPDATE sessions SET rec = ? WHERE id = ?",
-			 DB_INT, rec, DB_INT, session->get_session_id(session));
+			 DB_INT, rec, DB_INT, session->get_session_id(session, NULL, NULL));
 }
 
 METHOD(imv_database_t, policy_script, bool,
 	private_imv_database_t *this, imv_session_t *session, bool start)
 {
-	imv_workitem_t *workitem;
-	imv_workitem_type_t type;
-	int id, session_id, arg_int, rec_fail, rec_noresult;
-	enumerator_t *e;
-	char command[512], resp[128], *last, *arg_str;
+	char command[512], resp[128], *last;
 	FILE *shell;
 
-	session_id = session->get_session_id(session);
+	if (start)
+	{
+		if (session->get_policy_started(session))
+		{
+			DBG1(DBG_IMV, "policy script as already been started");
+			return FALSE;
+		}
 
-	snprintf(command, sizeof(command), "2>&1 TNC_SESSION_ID='%d' %s %s",
-			 session_id, this->script, start ? "start" : "stop");
+		/* add product info and device ID to session DB entry */
+		if (!create_session(this, session))
+		{
+			return FALSE;
+		}
+	}
+	else
+	{
+		if (!session->get_policy_started(session))
+		{
+			DBG1(DBG_IMV, "policy script as already been stopped");
+			return FALSE;
+		}
+	}
+
+	/* call the policy script */
+	snprintf(command, sizeof(command), "2>&1 %s %s %d",
+			 this->script, start ? "start" : "stop",
+			 session->get_session_id(session, NULL, NULL));
 	DBG3(DBG_IMV, "running policy script: %s", command);
 
 	shell = popen(command, "r");
@@ -282,30 +296,16 @@ METHOD(imv_database_t, policy_script, bool,
 	}
 	pclose(shell);
 
-	if (start && !session->get_policy_started(session))
+	if (start)
 	{
-		/* get workitem list generated by policy manager */
-		e = this->db->query(this->db,
-				"SELECT id, type, arg_str, arg_int, rec_fail, rec_noresult "
-				"FROM workitems WHERE session = ?",	DB_INT, session_id,
-				 DB_INT, DB_INT, DB_TEXT, DB_INT,DB_INT, DB_INT);
-		if (!e)
+		/* add workitem list generated by policy manager to session object */
+		if (!add_workitems(this, session))
 		{
-			DBG1(DBG_IMV, "no workitem enumerator returned");
 			return FALSE;
 		}
-		while (e->enumerate(e, &id, &type, &arg_str, &arg_int, &rec_fail,
-							   &rec_noresult))
-		{
-			workitem = imv_workitem_create(id, type, arg_str, arg_int, rec_fail,
-										   rec_noresult);
-			session->insert_workitem(session, workitem);
-		}
-		e->destroy(e);
-
 		session->set_policy_started(session, TRUE);
 	}
-	else if (!start && session->get_policy_started(session))
+	else
 	{
 		session->set_policy_started(session, FALSE);
 	}
@@ -327,19 +327,10 @@ METHOD(imv_database_t, finalize_workitem, bool,
 				DB_INT, workitem->get_id(workitem)) == 1;
 }
 
-METHOD(imv_database_t, get_database, database_t*,
-	private_imv_database_t *this)
-{
-	return this->db;
-}
-
 METHOD(imv_database_t, destroy, void,
 	private_imv_database_t *this)
 {
 	DESTROY_IF(this->db);
-	this->sessions->destroy_offset(this->sessions,
-							offsetof(imv_session_t, destroy));
-	this->mutex->destroy(this->mutex);
 	free(this);
 }
 
@@ -352,20 +343,14 @@ imv_database_t *imv_database_create(char *uri, char *script)
 
 	INIT(this,
 		.public = {
-			.add_session = _add_session,
-			.remove_session = _remove_session,
-			.add_product = _add_product,
-			.add_device = _add_device,
-			.add_recommendation = _add_recommendation,
+			.get_database = _get_database,
 			.policy_script = _policy_script,
 			.finalize_workitem = _finalize_workitem,
-			.get_database = _get_database,
+			.add_recommendation = _add_recommendation,
 			.destroy = _destroy,
 		},
 		.db = lib->db->create(lib->db, uri),
 		.script = script,
-		.sessions = linked_list_create(),
-		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
 	);
 
 	if (!this->db)
@@ -378,4 +363,3 @@ imv_database_t *imv_database_create(char *uri, char *script)
 
 	return &this->public;
 }
-
diff --git a/src/libimcv/imv/imv_database.h b/src/libimcv/imv/imv_database.h
index 48a3ded..79551cc 100644
--- a/src/libimcv/imv/imv_database.h
+++ b/src/libimcv/imv/imv_database.h
@@ -56,26 +56,6 @@ struct imv_database_t {
 	 void (*remove_session)(imv_database_t *this, imv_session_t *session);
 
 	/**
-	 * Add product information string to a session database entry
-	 *
-	 * @param session		Session
-	 * @param product		Product information string
-	 * @return				Product ID
-	 */
-	 int (*add_product)(imv_database_t *this, imv_session_t *session,
-						char *product);
-
-	/**
-	 * Add device identification to a session database entry
-	 *
-	 * @param session		Session
-	 * @param device		Device identification
-	 * @return				Device ID
-	 */
-	 int (*add_device)(imv_database_t *this, imv_session_t *session,
-					   chunk_t device);
-
-	/**
 	 * Add final recommendation to a session database entry
 	 *
 	 * @param session		Session
diff --git a/src/libimcv/imv/imv_if.h b/src/libimcv/imv/imv_if.h
index fa9765b..2118509 100644
--- a/src/libimcv/imv/imv_if.h
+++ b/src/libimcv/imv/imv_if.h
@@ -26,10 +26,10 @@ static imv_agent_if_t *imv_agent;
 /*
  * see section 3.8.1 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
-							  TNC_Version min_version,
-							  TNC_Version max_version,
-							  TNC_Version *actual_version)
+TNC_Result TNC_IMV_API TNC_IMV_Initialize(TNC_IMVID imv_id,
+										  TNC_Version min_version,
+										  TNC_Version max_version,
+										  TNC_Version *actual_version)
 {
 	if (imv_agent)
 	{
@@ -54,9 +54,9 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
 /**
  * see section 3.8.2 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
-										  TNC_ConnectionID connection_id,
-										  TNC_ConnectionState new_state)
+TNC_Result TNC_IMV_API TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
+												TNC_ConnectionID connection_id,
+												TNC_ConnectionState new_state)
 {
 	if (!imv_agent)
 	{
@@ -70,11 +70,11 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
 /**
  * see section 3.8.4 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
-								  TNC_ConnectionID connection_id,
-								  TNC_BufferReference msg,
-								  TNC_UInt32 msg_len,
-								  TNC_MessageType msg_type)
+TNC_Result TNC_IMV_API TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
+											  TNC_ConnectionID connection_id,
+											  TNC_BufferReference msg,
+											  TNC_UInt32 msg_len,
+											  TNC_MessageType msg_type)
 {
 	if (!imv_agent)
 	{
@@ -88,15 +88,15 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
 /**
  * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
-									  TNC_ConnectionID connection_id,
-									  TNC_UInt32 msg_flags,
-									  TNC_BufferReference msg,
-									  TNC_UInt32 msg_len,
-									  TNC_VendorID msg_vid,
-									  TNC_MessageSubtype msg_subtype,
-									  TNC_UInt32 src_imc_id,
-									  TNC_UInt32 dst_imv_id)
+TNC_Result TNC_IMV_API TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
+												  TNC_ConnectionID connection_id,
+												  TNC_UInt32 msg_flags,
+												  TNC_BufferReference msg,
+												  TNC_UInt32 msg_len,
+												  TNC_VendorID msg_vid,
+												  TNC_MessageSubtype msg_subtype,
+												  TNC_UInt32 src_imc_id,
+												  TNC_UInt32 dst_imv_id)
 {
 	if (!imv_agent)
 	{
@@ -111,8 +111,8 @@ TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
 /**
  * see section 3.8.7 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
-										 TNC_ConnectionID connection_id)
+TNC_Result TNC_IMV_API TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
+												TNC_ConnectionID connection_id)
 {
 
 	if (!imv_agent)
@@ -126,7 +126,8 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
 /**
  * see section 3.8.8 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id)
+TNC_Result TNC_IMV_API TNC_IMV_BatchEnding(TNC_IMVID imv_id,
+										   TNC_ConnectionID connection_id)
 {
 	if (!imv_agent)
 	{
@@ -139,7 +140,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, TNC_ConnectionID connection_id)
 /**
  * see section 3.8.9 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
+TNC_Result TNC_IMV_API TNC_IMV_Terminate(TNC_IMVID imv_id)
 {
 	if (!imv_agent)
 	{
@@ -155,8 +156,8 @@ TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
 /**
  * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
-									   TNC_TNCS_BindFunctionPointer bind_function)
+TNC_Result TNC_IMV_API TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
+								TNC_TNCS_BindFunctionPointer bind_function)
 {
 	if (!imv_agent)
 	{
diff --git a/src/libimcv/imv/imv_os_info.c b/src/libimcv/imv/imv_os_info.c
new file mode 100644
index 0000000..dfab194
--- /dev/null
+++ b/src/libimcv/imv/imv_os_info.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 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 "imv_os_info.h"
+
+typedef struct private_imv_os_info_t private_imv_os_info_t;
+
+/**
+ * Private data of an imv_os_info_t object.
+ *
+ */
+struct private_imv_os_info_t {
+
+	/**
+	 * Public imv_os_info_t interface.
+	 */
+	imv_os_info_t public;
+
+	/**
+	 * OS type
+	 */
+	os_type_t type;
+
+	/**
+	 * OS name
+	 */
+	chunk_t name;
+
+	/**
+	 * OS version
+	 */
+	chunk_t version;
+
+	/**
+	 * This flag allows the OS version to be empty
+	 */
+	bool version_is_set;
+
+	/**
+	 * OS Product Information (OS Name | OS Version)
+	 */
+	char *info;
+
+};
+
+METHOD(imv_os_info_t, get_type, os_type_t,
+	private_imv_os_info_t *this)
+{
+	return this->type;
+}
+
+METHOD(imv_os_info_t, set_name, void,
+	private_imv_os_info_t *this, chunk_t name)
+{
+	/* Has the OS name already been set? */
+	if (this->name.len)
+	{
+		if (chunk_equals(name, this->name))
+		{
+			return;
+		}
+		free(this->name.ptr);
+
+		/* Also clear the OS info string */
+		free(this->info);
+		this->info = NULL;
+	}
+	this->name = chunk_clone(name);
+	this->type = os_type_from_name(name); 
+}
+
+METHOD(imv_os_info_t, get_name, chunk_t,
+	private_imv_os_info_t *this)
+{
+	return this->name;
+}
+
+METHOD(imv_os_info_t, set_version, void,
+	private_imv_os_info_t *this, chunk_t version)
+{
+	/* Has the OS version already been set? */
+	if (this->version_is_set)
+	{
+		if (chunk_equals(version, this->version))
+		{
+			return;
+		}
+		free(this->version.ptr);
+
+		/* Also clear the OS info string */
+		free(this->info);
+		this->info = NULL;
+	}
+	this->version = chunk_clone(version);
+	this->version_is_set = TRUE;
+}
+
+METHOD(imv_os_info_t, get_version, chunk_t,
+	private_imv_os_info_t *this)
+{
+	return this->version;
+}
+
+METHOD(imv_os_info_t, get_info, char*,
+	private_imv_os_info_t *this)
+{
+	int len;
+
+	if (!this->info)
+	{
+		/* Have both OS name and OS version been set? */
+		if (this->name.len == 0 || !this->version_is_set)
+		{
+			return NULL;
+		}
+
+		/* OS info is a concatenation of OS name and OS version */
+		len = this->name.len + 1 + this->version.len + 1;
+		this->info = malloc(len);
+		snprintf(this->info, len, "%.*s %.*s",
+				(int)this->name.len, this->name.ptr,
+				(int)this->version.len, this->version.ptr);
+	}
+	return this->info;
+}
+
+METHOD(imv_os_info_t, destroy, void,
+	private_imv_os_info_t *this)
+{
+	free(this->name.ptr);
+	free(this->version.ptr);
+	free(this->info);
+	free(this);
+}
+
+/**
+ * See header
+ */
+imv_os_info_t *imv_os_info_create(void)
+{
+	private_imv_os_info_t *this;
+
+	INIT(this,
+		.public = {
+			.get_type = _get_type,
+			.set_name = _set_name,
+			.get_name = _get_name,
+			.set_version = _set_version,
+			.get_version = _get_version,
+			.get_info = _get_info,
+			.destroy = _destroy,
+		},
+	);
+
+	return &this->public;
+}
diff --git a/src/libimcv/imv/imv_os_info.h b/src/libimcv/imv/imv_os_info.h
new file mode 100644
index 0000000..b68a17e
--- /dev/null
+++ b/src/libimcv/imv/imv_os_info.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 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 imv_os_info imv_os_info
+ * @{ @ingroup libimcv
+ */
+
+#ifndef IMV_OS_INFO_H_
+#define IMV_OS_INFO_H_
+
+typedef struct imv_os_info_t imv_os_info_t;
+
+#include "os_info/os_info.h"
+
+#include <library.h>
+
+/**
+ * Interface for the IMV Operating System (OS) information module
+ */
+struct imv_os_info_t {
+
+	/**
+	 * Get the OS type
+	 *
+	 * @return					OS type
+	 */
+	os_type_t (*get_type)(imv_os_info_t *this);
+
+	/**
+	 * Set the OS product name or distribution
+	 *
+	 * @param name				OS name
+	 */
+	void (*set_name)(imv_os_info_t *this, chunk_t name);
+
+	/**
+	 * Get the OS product name or distribution
+	 *
+	 * @return					OS name
+	 */
+	chunk_t (*get_name)(imv_os_info_t *this);
+
+	/**
+	 * Set the OS version or release
+	 *
+	 * @param version			OS version
+	 */
+	void (*set_version)(imv_os_info_t *this, chunk_t version);
+
+	/**
+	 * Get the OS version or release
+	 *
+	 * @return					OS version
+	 */
+	chunk_t (*get_version)(imv_os_info_t *this);
+
+	/**
+	 * Get the OS version or release
+	 *
+	 * @return					OS name | OS version
+	 */
+	char* (*get_info)(imv_os_info_t *this);
+
+	/**
+	 * Destroys an imv_os_info_t object.
+	 */
+	void (*destroy)(imv_os_info_t *this);
+};
+
+/**
+ * Create an imv_os_info_t object
+ */
+imv_os_info_t* imv_os_info_create(void);
+
+#endif /** IMV_OS_INFO_H_ @}*/
diff --git a/src/libimcv/imv/imv_policy_manager.c b/src/libimcv/imv/imv_policy_manager.c
index 028721a..50f7f2e 100644
--- a/src/libimcv/imv/imv_policy_manager.c
+++ b/src/libimcv/imv/imv_policy_manager.c
@@ -278,7 +278,7 @@ static bool policy_stop(database_t *db, int session_id)
 int main(int argc, char *argv[])
 {
 	database_t *db;
-	char *uri, *tnc_session_id;
+	char *uri;
 	int session_id;
 	bool start, success;
 
@@ -299,7 +299,7 @@ int main(int argc, char *argv[])
 		exit(SS_RC_INITIALIZATION_FAILED);
 	}
 
-	if (argc < 2)
+	if (argc < 3)
 	{
 		usage();
 		exit(SS_RC_INITIALIZATION_FAILED);
@@ -318,14 +318,7 @@ int main(int argc, char *argv[])
 		exit(SS_RC_INITIALIZATION_FAILED);
 	}
 
-	/* get session ID */
-	tnc_session_id = getenv("TNC_SESSION_ID");
-	if (!tnc_session_id)
-	{
-		fprintf(stderr, "environment variable TNC_SESSION_ID is not defined\n");
-		exit(SS_RC_INITIALIZATION_FAILED);
-	}
-	session_id = atoi(tnc_session_id);
+	session_id = atoi(argv[2]);
 
 	/* attach IMV database */
 	uri = lib->settings->get_str(lib->settings,
diff --git a/src/libimcv/imv/imv_policy_manager_usage.c b/src/libimcv/imv/imv_policy_manager_usage.c
index 3167a54..c71bc99 100644
--- a/src/libimcv/imv/imv_policy_manager_usage.c
+++ b/src/libimcv/imv/imv_policy_manager_usage.c
@@ -24,6 +24,5 @@ void usage(void)
 {
 	printf("\
 Usage:\n\
-  imv_policy_manager start|stop\n");
+  imv_policy_manager start|stop <tnc-session-id>\n");
 }
-
diff --git a/src/libimcv/imv/imv_session.c b/src/libimcv/imv/imv_session.c
index 754f1f7..1f0d8cf 100644
--- a/src/libimcv/imv/imv_session.c
+++ b/src/libimcv/imv/imv_session.c
@@ -35,11 +35,51 @@ struct private_imv_session_t {
 	int session_id;
 
 	/**
+	 * Unique Product ID
+	 */
+	int pid;
+
+	/**
+	 * Unique Device ID
+	 */
+	int did;
+
+	/**
 	 * TNCCS connection ID
 	 */
 	TNC_ConnectionID conn_id;
 
 	/**
+	 * Session creation time
+	 */
+	time_t created;
+
+	/**
+	 * Access Requestor ID type
+	 */
+	uint32_t ar_id_type;
+
+	/**
+	 * Access Requestor ID value
+	 */
+	chunk_t ar_id_value;
+
+	/**
+	 * OS information
+	 */
+	imv_os_info_t *os_info;
+
+	/**
+	 * Device ID
+	 */
+	chunk_t device_id;
+
+	/**
+	 * Is Device ID trusted?
+	 */
+	bool trusted;
+
+	/**
 	 * Have the workitems been generated?
 	 */
 	bool policy_started;
@@ -56,9 +96,25 @@ struct private_imv_session_t {
 
 };
 
+METHOD(imv_session_t, set_session_id, void,
+	private_imv_session_t *this, int session_id, int pid, int did)
+{
+	this->session_id = session_id;
+	this->pid = pid;
+	this->did = did;
+}
+
 METHOD(imv_session_t, get_session_id, int,
-	private_imv_session_t *this)
+	private_imv_session_t *this, int *pid, int *did)
 {
+	if (pid)
+	{
+		*pid = this->pid;
+	}
+	if (did)
+	{
+		*did = this->did;
+	}
 	return this->session_id;
 }
 
@@ -68,6 +124,72 @@ METHOD(imv_session_t, get_connection_id, TNC_ConnectionID,
 	return this->conn_id;
 }
 
+METHOD(imv_session_t, get_creation_time, time_t,
+	private_imv_session_t *this)
+{
+	return this->created;
+}
+
+METHOD(imv_session_t, get_ar_id, chunk_t,
+	private_imv_session_t *this, uint32_t *ar_id_type)
+{
+	if (ar_id_type)
+	{
+		*ar_id_type = this->ar_id_type;
+	}
+	return this->ar_id_value;
+}
+
+METHOD(imv_session_t, get_os_info, imv_os_info_t*,
+	private_imv_session_t *this)
+{
+	return this->os_info;
+}
+
+METHOD(imv_session_t, set_device_id, void,
+	private_imv_session_t *this, chunk_t device_id)
+{
+	if (device_id.len == 0)
+	{
+		device_id = chunk_from_str("unknown");
+	}
+	if (this->device_id.len)
+	{
+		if (chunk_equals(device_id, this->device_id))
+		{
+			return;
+		}
+		free(this->device_id.ptr);
+	}
+	this->device_id = chunk_clone(device_id);
+}
+
+METHOD(imv_session_t, get_device_id, bool,
+	private_imv_session_t *this, chunk_t *device_id)
+{
+	if (this->device_id.len == 0)
+	{
+		return FALSE;
+	}
+	if (device_id)
+	{
+		*device_id = this->device_id;
+	}
+	return TRUE;
+}
+
+METHOD(imv_session_t, set_device_trust, void,
+	private_imv_session_t *this, bool trusted)
+{
+	this->trusted = trusted;
+}
+
+METHOD(imv_session_t, get_device_trust, bool,
+	private_imv_session_t *this)
+{
+	return this->trusted;
+}
+
 METHOD(imv_session_t, set_policy_started, void,
 	private_imv_session_t *this, bool start)
 {
@@ -95,10 +217,6 @@ METHOD(imv_session_t, remove_workitem, void,
 METHOD(imv_session_t, create_workitem_enumerator, enumerator_t*,
 	private_imv_session_t *this)
 {
-	if (!this->policy_started)
-	{
-		return NULL;
-	}
 	return this->workitems->create_enumerator(this->workitems);
 }
 
@@ -137,6 +255,9 @@ METHOD(imv_session_t, destroy, void,
 	{
 		this->workitems->destroy_offset(this->workitems,
 								 offsetof(imv_workitem_t, destroy));
+		this->os_info->destroy(this->os_info);
+		free(this->ar_id_value.ptr);
+		free(this->device_id.ptr);
 		free(this);
 	}
 }
@@ -144,14 +265,23 @@ METHOD(imv_session_t, destroy, void,
 /**
  * See header
  */
-imv_session_t *imv_session_create(int session_id, TNC_ConnectionID conn_id)
+imv_session_t *imv_session_create(TNC_ConnectionID conn_id, time_t created,
+								  uint32_t ar_id_type, chunk_t ar_id_value)
 {
 	private_imv_session_t *this;
 
 	INIT(this,
 		.public = {
+			.set_session_id = _set_session_id,
 			.get_session_id = _get_session_id,
 			.get_connection_id = _get_connection_id,
+			.get_creation_time = _get_creation_time,
+			.get_ar_id = _get_ar_id,
+			.get_os_info = _get_os_info,
+			.set_device_id = _set_device_id,
+			.get_device_id = _get_device_id,
+			.set_device_trust = _set_device_trust,
+			.get_device_trust = _get_device_trust,
 			.set_policy_started = _set_policy_started,
 			.get_policy_started = _get_policy_started,
 			.insert_workitem = _insert_workitem,
@@ -161,8 +291,11 @@ imv_session_t *imv_session_create(int session_id, TNC_ConnectionID conn_id)
 			.get_ref = _get_ref,
 			.destroy = _destroy,
 		},
-		.session_id = session_id,
 		.conn_id = conn_id,
+		.created = created,
+		.ar_id_type = ar_id_type,
+		.ar_id_value = chunk_clone(ar_id_value),
+		.os_info = imv_os_info_create(),
 		.workitems = linked_list_create(),
 		.ref = 1,
 	);
diff --git a/src/libimcv/imv/imv_session.h b/src/libimcv/imv/imv_session.h
index 6b94523..42b9118 100644
--- a/src/libimcv/imv/imv_session.h
+++ b/src/libimcv/imv/imv_session.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -23,11 +23,13 @@
 #define  IMV_SESSION_H_
 
 #include "imv_workitem.h"
+#include "imv_os_info.h"
 
 #include <tncifimv.h>
-
 #include <library.h>
 
+#include <time.h>
+
 typedef struct imv_session_t imv_session_t;
 
 /**
@@ -36,11 +38,22 @@ typedef struct imv_session_t imv_session_t;
 struct imv_session_t {
 
 	/**
+	 * Set unique session ID
+	 *
+	 * @param session_id	primary key into sessions table
+	 * @param pid			primary key into products table
+	 * @param did			Primary key into devices table
+	 */
+	void (*set_session_id)(imv_session_t *this, int session_id, int pid, int did);
+
+	/**
 	 * Get unique session ID
 	 *
-	 * @return				Session ID
+	 * @param pid			primary key into products table
+	 * @param did			Primary key into devices table
+	 * @return				primary key into sessions table
 	 */
-	int (*get_session_id)(imv_session_t *this);
+	int (*get_session_id)(imv_session_t *this, int *pid, int *did);
 
 	/**
 	 * Get TNCCS Connection ID
@@ -50,6 +63,58 @@ struct imv_session_t {
 	TNC_ConnectionID (*get_connection_id)(imv_session_t *this);
 
 	/**
+	 * Get session creation time
+	 *
+	 * @return				Session creation time
+	 */
+	time_t (*get_creation_time)(imv_session_t *this);
+
+	/**
+	 * Get Access Requestor ID
+	 *
+	 * @param id_type		Access Requestor TCG Standard ID Type
+	 * @return				Access Requestor TCG Standard ID Value
+	 */
+	chunk_t (*get_ar_id)(imv_session_t *this, uint32_t *id_type);
+
+	/**
+	 * Get OS Information
+	 *
+	 * @return				OS info object
+	 */
+	imv_os_info_t* (*get_os_info)(imv_session_t *this);
+
+	/**
+	 * Set Device ID
+	 *
+	 * @param device_id		Device ID
+	 */
+	void (*set_device_id)(imv_session_t *this, chunk_t device_id);
+
+	/**
+	 * Get Device ID
+	 *
+	 * @param device_id		Device ID
+	 * @return				TRUE if Device ID has already been set
+	 */
+	bool (*get_device_id)(imv_session_t *this, chunk_t *device_id);
+
+	/**
+	 * Set trust into Device ID
+	 *
+	 * @param trusted		TRUE if Device ID is trusted
+	 */
+	void (*set_device_trust)(imv_session_t *this, bool trusted);
+
+
+	/**
+	 * Get device ID trust (needed for TPM-based attestation)
+	 *
+	 * @return				TRUE if Device ID is trusted
+	 */
+	bool (*get_device_trust)(imv_session_t *this);
+
+	/**
 	 * Set policy_started status
 	 *
 	 * @param start			TRUE if policy started, FALSE if policy stopped
@@ -105,9 +170,12 @@ struct imv_session_t {
 /**
  * Create an imv_session_t instance
  *
- * @param session_id		Unique Session ID
  * @param id				Associated Connection ID
+ * @param created			Session creation time
+ * @param ar_id_type		Access Requestor ID type
+ * @param ar_id_value		Access Requestor ID value
  */
-imv_session_t* imv_session_create(int session_id, TNC_ConnectionID id);
+imv_session_t* imv_session_create(TNC_ConnectionID id, time_t created,
+								  uint32_t ar_id_type, chunk_t ar_id_value);
 
 #endif /**  IMV_SESSION_H_ @}*/
diff --git a/src/libimcv/imv/imv_session_manager.c b/src/libimcv/imv/imv_session_manager.c
new file mode 100644
index 0000000..0fb8de4
--- /dev/null
+++ b/src/libimcv/imv/imv_session_manager.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014 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 "imv_session_manager.h"
+
+#include <threading/mutex.h>
+
+typedef struct private_imv_session_manager_t private_imv_session_manager_t;
+
+/**
+ * Private data of a imv_session_manager_t object.
+ */
+struct private_imv_session_manager_t {
+
+	/**
+	 * Public imv_session_manager_t interface.
+	 */
+	imv_session_manager_t public;
+
+	/**
+	 * Session list
+	 */
+	linked_list_t *sessions;
+
+	/**
+	 * mutex used to lock session list
+	 */
+	mutex_t *mutex;
+
+};
+
+METHOD(imv_session_manager_t, add_session, imv_session_t*,
+	private_imv_session_manager_t *this, TNC_ConnectionID conn_id,
+	uint32_t ar_id_type, chunk_t ar_id_value)
+{
+	enumerator_t *enumerator;
+	imv_session_t *current, *session = NULL;
+	time_t created;
+
+	this->mutex->lock(this->mutex);
+
+	/* check if a session has already been assigned */
+	enumerator = this->sessions->create_enumerator(this->sessions);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (conn_id == current->get_connection_id(current))
+		{
+			session = current;
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	/* session already exists */
+	if (session)
+	{
+		this->mutex->unlock(this->mutex);
+		return session->get_ref(session);
+	}
+
+	/* create a new session entry */
+	created = time(NULL);
+	session = imv_session_create(conn_id, created, ar_id_type, ar_id_value);
+	this->sessions->insert_last(this->sessions, session);
+
+	this->mutex->unlock(this->mutex);
+
+	return session;
+}
+
+METHOD(imv_session_manager_t, remove_session, void,
+	private_imv_session_manager_t *this, imv_session_t *session)
+{
+	enumerator_t *enumerator;
+	imv_session_t *current;
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->sessions->create_enumerator(this->sessions);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (current == session)
+		{
+			this->sessions->remove_at(this->sessions, enumerator);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
+METHOD(imv_session_manager_t, destroy, void,
+	private_imv_session_manager_t *this)
+{
+	this->sessions->destroy_offset(this->sessions,
+							offsetof(imv_session_t, destroy));
+	this->mutex->destroy(this->mutex);
+	free(this);
+}
+
+/**
+ * See header
+ */
+imv_session_manager_t *imv_session_manager_create(void)
+{
+	private_imv_session_manager_t *this;
+
+	INIT(this,
+		.public = {
+			.add_session = _add_session,
+			.remove_session = _remove_session,
+			.destroy = _destroy,
+		},
+		.sessions = linked_list_create(),
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+	);
+
+	return &this->public;
+}
+
diff --git a/src/libimcv/imv/imv_session_manager.h b/src/libimcv/imv/imv_session_manager.h
new file mode 100644
index 0000000..8a733ac
--- /dev/null
+++ b/src/libimcv/imv/imv_session_manager.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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 imv_session_manager_t imv_session_manager
+ * @{ @ingroup libimcv_imv
+ */
+
+#ifndef IMV_SESSION_MANAGER_H_
+#define IMV_SESSION_MANAGER_H_
+
+#include "imv_session.h"
+
+#include <tncifimv.h>
+
+#include <library.h>
+
+typedef struct imv_session_manager_t imv_session_manager_t;
+
+/**
+ * IMV session manager interface 
+ */
+struct imv_session_manager_t {
+
+	/**
+	 * Create or get a session associated with a TNCCS connection
+	 *
+	 * @param conn_id		TNCCS Connection ID
+	 * @param ar_id_type	Access Requestor identity type
+	 * @param ar_id_value	Access Requestor identity value
+	 * @return				Session associated with TNCCS Connection
+	 */
+	 imv_session_t* (*add_session)(imv_session_manager_t *this,
+								   TNC_ConnectionID conn_id,
+								   uint32_t ar_id_type, chunk_t ar_id_value);
+
+	/**
+	 * Remove a session
+	 *
+	 * @param session		Session
+	 */
+	 void (*remove_session)(imv_session_manager_t *this, imv_session_t *session);
+
+
+	/**
+	 * Destroys an imv_session_manager_t object
+	 */
+	void (*destroy)(imv_session_manager_t *this);
+};
+
+/**
+ * Create an imv_session_manager_t instance
+ */
+imv_session_manager_t* imv_session_manager_create();
+
+#endif /** IMV_SESSION_MANAGER_H_ @}*/
diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h
index 791846b..d11d15e 100644
--- a/src/libimcv/imv/imv_state.h
+++ b/src/libimcv/imv/imv_state.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -70,45 +70,28 @@ struct imv_state_t {
 	 *
 	 * @param max_msg_len	maximum size of a PA-TNC message
 	 */
-	void (*set_max_msg_len)(imv_state_t *this, u_int32_t max_msg_len);
+	void (*set_max_msg_len)(imv_state_t *this, uint32_t max_msg_len);
 
 	/**
 	 * Get the maximum size of a PA-TNC message for this TNCCS connection
 	 *
 	 * @return				maximum size of a PA-TNC message
 	 */
-	u_int32_t (*get_max_msg_len)(imv_state_t *this);
+	uint32_t (*get_max_msg_len)(imv_state_t *this);
 
 	/**
 	 * Set flags for completed actions
 	 *
 	 * @param flags			Flags to be set
 	 */
-	void (*set_action_flags)(imv_state_t *this, u_int32_t flags);
+	void (*set_action_flags)(imv_state_t *this, uint32_t flags);
 
 	/**
 	 * Get flags set for completed actions
 	 *
 	 * @return				Flags set for completed actions
 	 */
-	u_int32_t (*get_action_flags)(imv_state_t *this);
-
-	/**
-	 * Set Access Requestor ID
-	 *
-	 * @param id_type		Access Requestor TCG Standard ID Type
-	 * @param id_value		Access Requestor TCG Standard ID Value
-	 *
-	 */
-	void (*set_ar_id)(imv_state_t *this, u_int32_t id_type, chunk_t id_value);
-
-	/**
-	 * Get Access Requestor ID
-	 *
-	 * @param id_type		Access Requestor TCG Standard ID Type
-	 * @return				Access Requestor TCG Standard ID Value
-	 */
-	chunk_t (*get_ar_id)(imv_state_t *this, u_int32_t *id_type);
+	uint32_t (*get_action_flags)(imv_state_t *this);
 
 	/**
 	 * Set session associated with TNCCS Connection
diff --git a/src/libimcv/imv/tables-mysql.sql b/src/libimcv/imv/tables-mysql.sql
new file mode 100644
index 0000000..47ee41c
--- /dev/null
+++ b/src/libimcv/imv/tables-mysql.sql
@@ -0,0 +1,200 @@
+
+DROP TABLE IF EXISTS `directories`;
+CREATE TABLE `directories` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `path` VARCHAR(2048) NOT NULL
+);
+
+DROP TABLE IF EXISTS `files`;
+CREATE TABLE `files` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `dir` INTEGER DEFAULT 0 REFERENCES `directories`(`id`),
+  `name` VARCHAR(512) NOT NULL
+);
+
+DROP TABLE IF EXISTS `products`;
+CREATE TABLE `products` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `name` VARCHAR(128) NOT NULL
+);
+
+DROP TABLE IF EXISTS `algorithms`;
+CREATE TABLE `algorithms` (
+  `id` INTEGER PRIMARY KEY,
+  `name` VARCHAR(20) NOT NULL
+);
+
+DROP TABLE IF EXISTS `file_hashes`;
+CREATE TABLE `file_hashes` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `file` INTEGER NOT NULL REFERENCES `files`(`id`),
+  `product` INTEGER NOT NULL REFERENCES `products`(`id`),
+  `device` INTEGER DEFAULT 0,
+  `key` INTEGER DEFAULT 0 REFERENCES `keys`(id),
+  `algo` INTEGER NOT NULL REFERENCES `algorithms`(`id`),
+  `hash` VARBINARY(64) NOT NULL
+);
+
+DROP TABLE IF EXISTS `keys`;
+CREATE TABLE `keys` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `keyid` VARBINARY(128) NOT NULL,
+  `owner` VARCHAR(128) NOT NULL
+);
+
+DROP TABLE IF EXISTS `groups`;
+CREATE TABLE `groups` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `name` VARCHAR(50) NOT NULL UNIQUE,
+  `parent` INTEGER
+);
+
+DROP TABLE IF EXISTS `groups_members`;
+CREATE TABLE `groups_members` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `group_id` INTEGER NOT NULL REFERENCES `groups`(`id`),
+  `device_id` INTEGER NOT NULL REFERENCES `devices`(`id`),
+  UNIQUE (`group_id`, `device_id`)
+);
+
+DROP TABLE IF EXISTS `groups_product_defaults`;
+CREATE TABLE `groups_product_defaults` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `group_id` INTEGER NOT NULL REFERENCES `groups`(`id`),
+  `product_id` INTEGER NOT NULL REFERENCES `products`(`id`),
+  UNIQUE (`group_id`, `product_id`)
+);
+
+DROP TABLE IF EXISTS `policies`;
+CREATE TABLE `policies` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `type` INTEGER NOT NULL,
+  `name` VARCHAR(100) NOT NULL UNIQUE,
+  `argument` VARCHAR(100) DEFAULT '' NOT NULL,
+  `rec_fail` INTEGER NOT NULL,
+  `rec_noresult` INTEGER NOT NULL,
+  `file` INTEGER DEFAULT 0 REFERENCES `files`(`id`),
+  `dir` INTEGER DEFAULT 0 REFERENCES `directories`(`id`)
+);
+
+DROP TABLE IF EXISTS `enforcements`;
+CREATE TABLE `enforcements` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `policy` INTEGER NOT NULL REFERENCES `policies`(`id`),
+  `group_id` INTEGER NOT NULL REFERENCES `groups`(`id`),
+  `rec_fail` INTEGER,
+  `rec_noresult` INTEGER,
+  `max_age` INTEGER NOT NULL,
+  UNIQUE (`policy`, `group_id`)
+);
+
+DROP TABLE IF EXISTS `sessions`;
+CREATE TABLE `sessions` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `time` INTEGER NOT NULL,
+  `connection` INTEGER NOT NULL,
+  `identity` INTEGER DEFAULT 0 REFERENCES `identities`(`id`),
+  `device` INTEGER DEFAULT 0 REFERENCES `devices`(`id`),
+  `product` INTEGER DEFAULT 0 REFERENCES `products`(`id`),
+  `rec` INTEGER DEFAULT 3
+);
+
+DROP TABLE IF EXISTS `workitems`;
+CREATE TABLE `workitems` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `session` INTEGER NOT NULL REFERENCES `sessions`(`id`),
+  `enforcement` INTEGER NOT NULL REFERENCES `enforcements`(`id`),
+  `type` INTEGER NOT NULL,
+  `arg_str` VARCHAR(128),
+  `arg_int` INTEGER DEFAULT 0,
+  `rec_fail` INTEGER NOT NULL,
+  `rec_noresult` INTEGER NOT NULL,
+  `rec_final` INTEGER,
+  `result` VARCHAR(128)
+);
+
+DROP TABLE IF EXISTS `results`;
+CREATE TABLE `results` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `session` INTEGER NOT NULL REFERENCES `measurements`(`id`),
+  `policy` INTEGER NOT NULL REFERENCES `policies`(`id`),
+  `rec` INTEGER NOT NULL,
+  `result` TEXT NOT NULL
+);
+
+DROP TABLE IF EXISTS `components`;
+CREATE TABLE `components` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `vendor_id` INTEGER NOT NULL,
+  `name` INTEGER NOT NULL,
+  `qualifier` INTEGER DEFAULT 0
+);
+
+DROP TABLE IF EXISTS `key_component`;
+CREATE TABLE `key_component` (
+  `key` INTEGER NOT NULL,
+  `component` INTEGER NOT NULL,
+  `depth` INTEGER DEFAULT 0,
+  `seq_no` INTEGER DEFAULT 0,
+  PRIMARY KEY (`key`, `component`)
+);
+
+DROP TABLE IF EXISTS `component_hashes`;
+CREATE TABLE `component_hashes` (
+  `component` INTEGER NOT NULL,
+  `key` INTEGER NOT NULL,
+  `seq_no` INTEGER NOT NULL,
+  `pcr` INTEGER NOT NULL,
+  `algo` INTEGER NOT NULL,
+  `hash` VARBINARY(32) NOT NULL,
+  PRIMARY KEY(`component`, `key`, `seq_no`, `algo`)
+);
+
+DROP TABLE IF EXISTS `packages`;
+CREATE TABLE `packages` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `name` VARCHAR(128) NOT NULL,
+  `blacklist` INTEGER DEFAULT 0
+);
+
+DROP TABLE IF EXISTS versions;
+CREATE TABLE versions (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `package` INTEGER NOT NULL REFERENCES packages(id),
+  `product` INTEGER NOT NULL REFERENCES products(id),
+  `release` VARCHAR(32) NOT NULL,
+  `security` INTEGER DEFAULT 0,
+  `blacklist` INTEGER DEFAULT 0,
+  `time` INTEGER DEFAULT 0
+);
+
+DROP TABLE IF EXISTS `devices`;
+CREATE TABLE `devices` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `description` VARCHAR(100) DEFAULT "",
+  `value` VARCHAR(256) NOT NULL,
+  `product` INTEGER REFERENCES `products`(`id`),
+  `created` INTEGER
+);
+
+DROP TABLE IF EXISTS `identities`;
+CREATE TABLE `identities` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `type` INTEGER NOT NULL,
+  `value` VARBINARY(128) NOT NULL,
+  UNIQUE (type, value)
+);
+
+DROP TABLE IF EXISTS `regids`;
+CREATE TABLE `regids` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `name` TEXT NOT NULL
+);
+
+DROP TABLE IF EXISTS `tags`;
+CREATE TABLE `tags` (
+  `id` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  `regid` INTEGER NOT NULL REFERENCES `regids`(`id`),
+  `unique_sw_id` VARCHAR(64) NOT NULL,
+  `value` VARCHAR(128)
+);
diff --git a/src/libimcv/imv/tables.sql b/src/libimcv/imv/tables.sql
index a0f3a4e..f732489 100644
--- a/src/libimcv/imv/tables.sql
+++ b/src/libimcv/imv/tables.sql
@@ -42,27 +42,11 @@ CREATE TABLE file_hashes (
   id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
   file INTEGER NOT NULL REFERENCES files(id),
   product INTEGER NOT NULL REFERENCES products(id),
-  device INTEGER DEFAULT 0,
-  key INTEGER DEFAULT 0 REFERENCES keys(id),
+  device INTEGER DEFAULT 0 REFERENCES devices(id),
   algo INTEGER NOT NULL REFERENCES algorithms(id),
   hash BLOB NOT NULL
 );
 
-DROP TABLE IF EXISTS keys;
-CREATE TABLE keys (
-  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
-  keyid BLOB NOT NULL,
-  owner TEXT NOT NULL
-);
-DROP INDEX IF EXISTS keys_keyid;
-CREATE INDEX keys_keyid ON keys (
-  keyid
-);
-DROP INDEX IF EXISTS keys_owner;
-CREATE INDEX keys_owner ON keys (
-  owner
-);
-
 DROP TABLE IF EXISTS groups;
 CREATE TABLE groups (
   id INTEGER NOT NULL PRIMARY KEY,
@@ -156,29 +140,19 @@ CREATE TABLE components (
   id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
   vendor_id INTEGER NOT NULL,
   name INTEGER NOT NULL,
-  qualifier INTEGER DEFAULT 0
+  qualifier INTEGER DEFAULT 0,
+  label TEXT NOT NULL
 );
 
-
-DROP TABLE IF EXISTS key_component;
-CREATE TABLE key_component (
-  key INTEGER NOT NULL,
-  component INTEGER NOT NULL,
-  depth INTEGER DEFAULT 0,
-  seq_no INTEGER DEFAULT 0,
-  PRIMARY KEY (key, component)
-);
-
-
 DROP TABLE IF EXISTS component_hashes;
 CREATE TABLE component_hashes (
-  component INTEGER NOT NULL,
-  key INTEGER NOT NULL,
+  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  component INTEGER NOT NULL REFERENCES components(id),
+  key INTEGER NOT NULL REFERENCES devices(id),
   seq_no INTEGER NOT NULL,
   pcr INTEGER NOT NULL,
-  algo INTEGER NOT NULL,
-  hash BLOB NOT NULL,
-  PRIMARY KEY(component, key, seq_no, algo)
+  algo INTEGER NOT NULL REFERENCES algorithms(id),
+  hash BLOB NOT NULL
 );
 
 DROP TABLE IF EXISTS packages;
@@ -217,6 +191,7 @@ CREATE TABLE devices (
   description TEXT DEFAULT '',
   value TEXT NOT NULL,
   product INTEGER REFERENCES products(id),
+  trusted INTEGER DEFAULT 0,
   created INTEGER
 );
 DROP INDEX IF EXISTS devices_id;
@@ -232,25 +207,101 @@ CREATE TABLE identities (
   UNIQUE (type, value)
 );
 
-DROP TABLE IF EXISTS regids;
-CREATE TABLE regids (
-  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
-  name TEXT NOT NULL
+DROP TABLE IF EXISTS "swid_entities";
+CREATE TABLE "swid_entities" (
+  "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  "name" VARCHAR(255) NOT NULL,
+  "regid" VARCHAR(255) NOT NULL
 );
-DROP INDEX IF EXISTS regids_name;
-CREATE INDEX regids_name ON regids (
-  name
+DROP INDEX IF EXISTS "swid_entities_name";
+DROP INDEX IF EXISTS "swid_entities_regid";
+CREATE INDEX "swid_entities_name" ON "swid_entities" (
+  "name"
+);
+CREATE INDEX "swid_entities_regid" ON "swid_entities" (
+  "regid"
 );
 
-DROP TABLE IF EXISTS tags;
-CREATE TABLE tags (
-  id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
-  regid INTEGER NOT NULL REFERENCES regids(id),
-  unique_sw_id TEXT NOT NULL,
-  value TEXT
+DROP TABLE IF EXISTS "swid_entityroles";
+CREATE TABLE "swid_entityroles" (
+  "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  "tag_id" INTEGER NOT NULL REFERENCES "swid_tags" ("id"),
+  "entity_id" INTEGER NOT NULL,
+  "role" SMALLINT UNSIGNED NOT NULL
+);
+DROP INDEX if EXISTS "swid_entityroles_tag_id";
+DROP INDEX IF EXISTS "swid_entityroles_tag_entity_id";
+CREATE INDEX "swid_entityroles_tag_id" ON "swid_entityroles" (
+  "tag_id"
+);
+CREATE INDEX "swid_entityroles_entity_id" ON "swid_entityroles" (
+  "entity_id"
+);
+
+DROP TABLE IF EXISTS "swid_tags";
+CREATE TABLE "swid_tags" (
+  "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  "package_name" VARCHAR(255) NOT NULL,
+  "version" VARCHAR(255) NOT NULL,
+  "unique_id" VARCHAR(255) NOT NULL,
+  "swid_xml" TEXT NOT NULL,
+  "software_id" VARCHAR(255) NOT NULL
+);
+DROP INDEX if EXISTS "swid_tags_unique_id";
+DROP INDEX IF EXISTS "swid_tags_package_name";
+DROP INDEX IF EXISTS "swid_tags_software_id";
+CREATE INDEX "swid_tags_unique_id" ON "swid_tags" (
+  "unique_id"
+);
+CREATE INDEX "swid_tags_package_name" ON "swid_tags" (
+  "package_name"
+);
+CREATE INDEX "swid_tags_software_id" ON "swid_tags" (
+  "software_id"
+);
+
+DROP TABLE IF EXISTS "swid_tags_files";
+CREATE TABLE "swid_tags_files" (
+  "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  "tag_id" INTEGER NOT NULL,
+  "file_id" INTEGER NOT NULL REFERENCES "files" ("id"),
+  UNIQUE ("tag_id", "file_id")
+);
+DROP INDEX IF EXISTS "swid_tags_files_file_id";
+DROP INDEX IF EXISTS "swid_tags_files_tag_id";
+CREATE INDEX "swid_tags_files_file_id" ON "swid_tags_files" (
+  "file_id"
+);
+CREATE INDEX "swid_tags_files_tag_id" ON "swid_tags_files" (
+  "tag_id"
+);
+
+DROP TABLE IF EXISTS "swid_tags_sessions";
+CREATE TABLE "swid_tags_sessions" (
+  "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  "tag_id" INTEGER NOT NULL,
+  "session_id" INTEGER NOT NULL REFERENCES "sessions" ("id"),
+  UNIQUE ("tag_id", "session_id")
+);
+DROP INDEX IF EXISTS "swid_tags_sessions_tag_id";
+DROP INDEX IF EXISTS "swid_tags_sessions_session_id";
+CREATE INDEX "swid_tags_sessions_tag_id" ON "swid_tags_sessions" (
+  "tag_id"
 );
-DROP INDEX IF EXISTS tags_name;
-CREATE INDEX tags_unique_sw_id ON tags (
-  unique_sw_id
+CREATE INDEX "swid_tags_sessions_session_id" ON "swid_tags_sessions" (
+"session_id"
 );
 
+DROP TABLE IF EXISTS "swid_tagstats";
+CREATE TABLE "swid_tagstats" (
+  "id" integer NOT NULL PRIMARY KEY,
+  "tag_id" integer NOT NULL REFERENCES "swid_tags" ("id"),
+  "device_id" integer NOT NULL REFERENCES "devices" ("id"),
+  "first_seen_id" integer NOT NULL REFERENCES "sessions" ("id"),
+  "last_seen_id" integer NOT NULL REFERENCES "sessions" ("id"),
+  UNIQUE ("tag_id", "device_id")
+);
+CREATE INDEX "swid_tagstats_tag_id" ON "swid_tagstats" ("tag_id");
+CREATE INDEX "swid_tagstats_device_id" ON "swid_tagstats" ("device_id");
+CREATE INDEX "swid_tagstats_first_seen_id" ON "swid_tagstats" ("first_seen_id");
+CREATE INDEX "swid_tagstats_last_seen_id" ON "swid_tagstats" ("last_seen_id");
diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c
index 0642757..258b8b4 100644
--- a/src/libimcv/os_info/os_info.c
+++ b/src/libimcv/os_info/os_info.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -15,16 +15,7 @@
 
 #include "os_info.h"
 
-#include <sys/utsname.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#include <collections/linked_list.h>
-#include <utils/debug.h>
-
-typedef struct private_os_info_t private_os_info_t;
-
-ENUM(os_type_names, OS_TYPE_UNKNOWN, OS_TYPE_ANDROID,
+ENUM(os_type_names, OS_TYPE_UNKNOWN, OS_TYPE_WINDOWS,
 	"Unknown",
 	"Debian",
 	"Ubuntu",
@@ -33,7 +24,8 @@ ENUM(os_type_names, OS_TYPE_UNKNOWN, OS_TYPE_ANDROID,
 	"CentOS",
 	"SUSE",
 	"Gentoo",
-	"Android"
+	"Android",
+	"Windows",
 );
 
 ENUM(os_fwd_status_names, OS_FWD_DISABLED, OS_FWD_UNKNOWN,
@@ -49,487 +41,6 @@ ENUM(os_package_state_names, OS_PACKAGE_STATE_UPDATE, OS_PACKAGE_STATE_BLACKLIST
 );
 
 /**
- * Private data of an os_info_t object.
- *
- */
-struct private_os_info_t {
-
-	/**
-	 * Public os_info_t interface.
-	 */
-	os_info_t public;
-
-	/**
-	 * OS type
-	 */
-	os_type_t type;
-
-	/**
-	 * OS name
-	 */
-	chunk_t name;
-
-	/**
-	 * OS version
-	 */
-	chunk_t version;
-
-};
-
-METHOD(os_info_t, get_type, os_type_t,
-	private_os_info_t *this)
-{
-	return this->type;
-}
-
-METHOD(os_info_t, get_name, chunk_t,
-	private_os_info_t *this)
-{
-	return this->name;
-}
-
-METHOD(os_info_t, get_numeric_version, void,
-	private_os_info_t *this, u_int32_t *major, u_int32_t *minor)
-{
-	u_char *pos;
-
-	if (major)
-	{
-		*major = atol(this->version.ptr);
-	}
-	pos = memchr(this->version.ptr, '.', this->version.len);
-	if (minor)
-	{
-		*minor = pos ? atol(pos + 1) : 0;
-	}
-}
-
-METHOD(os_info_t, get_version, chunk_t,
-	private_os_info_t *this)
-{
-	return this->version;
-}
-
-METHOD(os_info_t, get_fwd_status, os_fwd_status_t,
-	private_os_info_t *this)
-{
-	const char ip_forward[] = "/proc/sys/net/ipv4/ip_forward";
-	char buf[2];
-	FILE *file;
-
-	os_fwd_status_t fwd_status = OS_FWD_UNKNOWN;
-
-	file = fopen(ip_forward, "r");
-	if (file)
-	{
-		if (fread(buf, 1, 1, file) == 1)
-		{
-			switch (buf[0])
-			{
-				case '0':
-					fwd_status = OS_FWD_DISABLED;
-					break;
-				case '1':
-					fwd_status = OS_FWD_ENABLED;
-					break;
-				default:
-					DBG1(DBG_IMC, "\"%s\" returns invalid value ", ip_forward);
-					break;
-			}
-		}
-		else
-		{
-			DBG1(DBG_IMC, "could not read from \"%s\"", ip_forward);
-		}
-		fclose(file);
-	}
-	else
-	{
-		DBG1(DBG_IMC, "failed to open \"%s\"", ip_forward);
-	}
-
-	return fwd_status;
-}
-
-METHOD(os_info_t, get_uptime, time_t,
-	private_os_info_t *this)
-{
-	const char proc_uptime[] = "/proc/uptime";
-	FILE *file;
-	u_int uptime;
-
-	file = fopen(proc_uptime, "r");
-	if (!file)
-	{
-		DBG1(DBG_IMC, "failed to open \"%s\"", proc_uptime);
-		return 0;
-	}
-	if (fscanf(file, "%u", &uptime) != 1)
-	{
-		DBG1(DBG_IMC, "failed to read file \"%s\"", proc_uptime);
-		uptime = 0;
-	}
-	fclose(file);
-
-	return uptime;
-}
-
-METHOD(os_info_t, get_setting, chunk_t,
-	private_os_info_t *this, char *name)
-{
-	FILE *file;
-	u_char buf[2048];
-	size_t i = 0;
-	chunk_t value;
-
-	if (!strpfx(name, "/etc/") && !strpfx(name, "/proc/") &&
-		!strpfx(name, "/sys/") && !strpfx(name, "/var/"))
-	{
-		/**
-		 * In order to guarantee privacy, only settings from the
-		 * /etc/, /proc/ and /sys/ directories can be retrieved
-		 */
-		DBG1(DBG_IMC, "not allowed to access '%s'", name);
-
-		return chunk_empty;
-	}
-
-	file = fopen(name, "r");
-	if (!file)
-	{
-		DBG1(DBG_IMC, "failed to open '%s'", name);
-
-		return chunk_empty;
-	}
-	while (i < sizeof(buf) && fread(buf + i, 1, 1, file) == 1)
-	{
-		i++;
-	}
-	fclose(file);
-
-	value = chunk_create(buf, i);
-
-	return chunk_clone(value);
-}
-
-typedef struct {
-	/**
-	 * implements enumerator_t
-	 */
-	enumerator_t public;
-
-	/**
-	 * package info pipe stream
-	 */
-	FILE* file;
-
-	/**
-	 * line buffer
-	 */
-	u_char line[512];
-
-} package_enumerator_t;
-
-/**
- * Implementation of package_enumerator.destroy.
- */
-static void package_enumerator_destroy(package_enumerator_t *this)
-{
-	pclose(this->file);
-	free(this);
-}
-
-/**
- * Implementation of package_enumerator.enumerate
- */
-static bool package_enumerator_enumerate(package_enumerator_t *this, ...)
-{
-	chunk_t *name, *version;
-	u_char *pos;
-	va_list args;
-
-	while (TRUE)
-	{
-		if (!fgets(this->line, sizeof(this->line), this->file))
-		{
-			return FALSE;
-		}
-
-		pos = strchr(this->line, '\t');
-		if (!pos)
-		{
-			return FALSE;
-		}
-		*pos++ = '\0';
-
-		if (!streq(this->line, "install ok installed"))
-		{
-			continue;
-		}
-		va_start(args, this);
-
-		name = va_arg(args, chunk_t*);
-		name->ptr = pos;
-		pos = strchr(pos, '\t');
-		if (!pos)
-		{
-			va_end(args);
-			return FALSE;
-		}
-		name->len = pos++ - name->ptr;
-
-		version = va_arg(args, chunk_t*);
-		version->ptr = pos;
-		version->len = strlen(pos) - 1;
-
-		va_end(args);
-		return TRUE;
-	}
-}
-
-METHOD(os_info_t, create_package_enumerator, enumerator_t*,
-	private_os_info_t *this)
-{
-	FILE *file;
-	const char command[] = "dpkg-query --show --showformat="
-								"'${Status}\t${Package}\t${Version}\n'";
-	package_enumerator_t *enumerator;
-
-	/* Only Debian and Ubuntu package enumeration is currently supported */
-	if (this->type != OS_TYPE_DEBIAN && this->type != OS_TYPE_UBUNTU)
-	{
-		return NULL;
-	}
-
-	/* Open a pipe stream for reading the output of the dpkg-query commmand */
-	file = popen(command, "r");
-	if (!file)
-	{
-		DBG1(DBG_IMC, "failed to run dpkg command");
-		return NULL;
-	}
-
-	/* Create a package enumerator instance */
-	enumerator = malloc_thing(package_enumerator_t);
-	enumerator->public.enumerate = (void*)package_enumerator_enumerate;
-	enumerator->public.destroy = (void*)package_enumerator_destroy;
-	enumerator->file = file;
-
-	return (enumerator_t*)enumerator;
-}
-
-
-METHOD(os_info_t, destroy, void,
-	private_os_info_t *this)
-{
-	free(this->name.ptr);
-	free(this->version.ptr);
-	free(this);
-}
-
-#define RELEASE_LSB		0
-#define RELEASE_DEBIAN	1
-
-/**
- * Determine Linux distribution version and hardware platform
- */
-static bool extract_platform_info(os_type_t *type, chunk_t *name,
-								  chunk_t *version)
-{
-	FILE *file;
-	u_char buf[BUF_LEN], *pos = buf;
-	int len = BUF_LEN - 1;
-	os_type_t os_type = OS_TYPE_UNKNOWN;
-	chunk_t os_name = chunk_empty;
-	chunk_t os_version = chunk_empty;
-	char *os_str;
-	struct utsname uninfo;
-	int i;
-
-	/* Linux/Unix distribution release info (from http://linuxmafia.com) */
-	const char* releases[] = {
-		"/etc/lsb-release",           "/etc/debian_version",
-		"/etc/SuSE-release",          "/etc/novell-release",
-		"/etc/sles-release",          "/etc/redhat-release",
-		"/etc/fedora-release",        "/etc/gentoo-release",
-		"/etc/slackware-version",     "/etc/annvix-release",
-		"/etc/arch-release",          "/etc/arklinux-release",
-		"/etc/aurox-release",         "/etc/blackcat-release",
-		"/etc/cobalt-release",        "/etc/conectiva-release",
-		"/etc/debian_release",        "/etc/immunix-release",
-		"/etc/lfs-release",           "/etc/linuxppc-release",
-		"/etc/mandrake-release",      "/etc/mandriva-release",
-		"/etc/mandrakelinux-release", "/etc/mklinux-release",
-		"/etc/pld-release",           "/etc/redhat_version",
-		"/etc/slackware-release",     "/etc/e-smith-release",
-		"/etc/release",               "/etc/sun-release",
-		"/etc/tinysofa-release",      "/etc/turbolinux-release",
-		"/etc/ultrapenguin-release",  "/etc/UnitedLinux-release",
-		"/etc/va-release",            "/etc/yellowdog-release"
-	};
-
-	const char lsb_distrib_id[]      = "DISTRIB_ID=";
-	const char lsb_distrib_release[] = "DISTRIB_RELEASE=";
-
-	for (i = 0; i < countof(releases); i++)
-	{
-		file = fopen(releases[i], "r");
-		if (!file)
-		{
-			continue;
-		}
-
-		/* read release file into buffer */
-		fseek(file, 0, SEEK_END);
-		len = min(ftell(file), 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;
-		}
-		fclose(file);
-
-		DBG1(DBG_IMC, "processing \"%s\" file", releases[i]);
-
-		switch (i)
-		{
-			case RELEASE_LSB:
-			{
-				/* Determine Distribution ID */
-				pos = strstr(buf, lsb_distrib_id);
-				if (!pos)
-				{
-					DBG1(DBG_IMC, "failed to find begin of DISTRIB_ID field");
-					return FALSE;
-				}
-				pos += strlen(lsb_distrib_id);
-
-				os_name.ptr = pos;
-
-				pos = strchr(pos, '\n');
-				if (!pos)
-				{
-					DBG1(DBG_IMC, "failed to find end of DISTRIB_ID field");
-					return FALSE;
-			 	}
-				os_name.len = pos - os_name.ptr;
-
-				/* Determine Distribution Release */
-				pos = strstr(buf, lsb_distrib_release);
-				if (!pos)
-				{
-					DBG1(DBG_IMC, "failed to find begin of DISTRIB_RELEASE field");
-					return FALSE;
-				}
-				pos += strlen(lsb_distrib_release);
-
-				os_version.ptr = pos;
-
-				pos = strchr(pos, '\n');
-				if (!pos)
-				{
-					DBG1(DBG_IMC, "failed to find end of DISTRIB_RELEASE field");
-					return FALSE;
-			 	}
-				os_version.len = pos - os_version.ptr;
-
-				break;
-			}
-			case RELEASE_DEBIAN:
-			{
-				os_type = OS_TYPE_DEBIAN;
-
-				os_version.ptr = buf;
-				pos = strchr(buf, '\n');
-				if (!pos)
-				{
-					DBG1(DBG_PTS, "failed to find end of release string");
-					return FALSE;
-				}
-
-				os_version.len = pos - os_version.ptr;
-
-				break;
-			}
-			default:
-			{
-				const char str_release[] = " release ";
-
-				os_name.ptr = buf;
-
-				pos = strstr(buf, str_release);
-				if (!pos)
-				{
-					DBG1(DBG_IMC, "failed to find release keyword");
-					return FALSE;
-				}
-
-				os_name.len = pos - os_name.ptr;
-
-				pos += strlen(str_release);
-				os_version.ptr = pos;
-
-				pos = strchr(pos, '\n');
-				if (!pos)
-				{
-					DBG1(DBG_IMC, "failed to find end of release string");
-					return FALSE;
-			 	}
-
-				os_version.len = pos - os_version.ptr;
-
-				break;
-			}
-		}
-		break;
-	}
-
-	if (!os_version.ptr)
-	{
-		DBG1(DBG_IMC, "no distribution release file found");
-		return FALSE;
-	}
-
-	if (uname(&uninfo) < 0)
-	{
-		DBG1(DBG_IMC, "could not retrieve machine architecture");
-		return FALSE;
-	}
-
-	/* Try to find a matching OS type based on the OS name */
-	if (os_type == OS_TYPE_UNKNOWN)
-	{
-		os_type = os_type_from_name(os_name);
-	}
-
-	/* If known use the official OS name */
-	if (os_type != OS_TYPE_UNKNOWN)
-	{
-		os_str = enum_to_name(os_type_names, os_type);
-		os_name = chunk_create(os_str, strlen(os_str));
-	}
-
-	/* copy OS type */
-	*type = os_type;
-
-	/* copy OS name */
-	*name = chunk_clone(os_name);
-
-	/* copy OS version and machine architecture */
-	*version = chunk_alloc(os_version.len + 1 + strlen(uninfo.machine));
-	pos = version->ptr;
-	memcpy(pos, os_version.ptr, os_version.len);
-	pos += os_version.len;
-	*pos++ = ' ';
-	memcpy(pos, uninfo.machine, strlen(uninfo.machine));
-
-	return TRUE;
-}
-
-/**
  * See header
  */
 os_type_t os_type_from_name(chunk_t name)
@@ -548,59 +59,3 @@ os_type_t os_type_from_name(chunk_t name)
 	}
 	return OS_TYPE_UNKNOWN;
 }
-
-/**
- * See header
- */
-os_info_t *os_info_create(void)
-{
-	private_os_info_t *this;
-	chunk_t name, version;
-	os_type_t type;
-
-	/* As an option OS name and OS version can be configured manually */
-	name.ptr = lib->settings->get_str(lib->settings,
-									  "%s.imcv.os_info.name", NULL, lib->ns);
-	version.ptr = lib->settings->get_str(lib->settings,
-									  "%s.imcv.os_info.version", NULL, lib->ns);
-	if (name.ptr && version.ptr)
-	{
-		name.len = strlen(name.ptr);
-		name = chunk_clone(name);
-
-		version.len = strlen(version.ptr);
-		version = chunk_clone(version);
-
-		type = os_type_from_name(name);
-	}
-	else
-	{
-		if (!extract_platform_info(&type, &name, &version))
-		{
-			return NULL;
-		}
-	}
-	DBG1(DBG_IMC, "operating system name is '%.*s'",
-				   name.len, name.ptr);
-	DBG1(DBG_IMC, "operating system version is '%.*s'",
-				   version.len, version.ptr);
-
-	INIT(this,
-		.public = {
-			.get_type = _get_type,
-			.get_name = _get_name,
-			.get_numeric_version = _get_numeric_version,
-			.get_version = _get_version,
-			.get_fwd_status = _get_fwd_status,
-			.get_uptime = _get_uptime,
-			.get_setting = _get_setting,
-			.create_package_enumerator = _create_package_enumerator,
-			.destroy = _destroy,
-		},
-		.type = type,
-		.name = name,
-		.version = version,
-	);
-
-	return &this->public;
-}
diff --git a/src/libimcv/os_info/os_info.h b/src/libimcv/os_info/os_info.h
index f474607..0313554 100644
--- a/src/libimcv/os_info/os_info.h
+++ b/src/libimcv/os_info/os_info.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@ enum os_type_t {
 	OS_TYPE_SUSE,
 	OS_TYPE_GENTOO,
 	OS_TYPE_ANDROID,
+	OS_TYPE_WINDOWS,
 	OS_TYPE_ROOF
 };
 
@@ -68,86 +69,11 @@ enum os_fwd_status_t {
 extern enum_name_t *os_fwd_status_names;
 
 /**
- * Interface for the Operating System (OS) information module
- */
-struct os_info_t {
-
-	/**
-	 * Get the OS type if it can be determined
-	 *
-	 * @return					OS type
-	 */
-	os_type_t (*get_type)(os_info_t *this);
-
-	/**
-	 * Get the OS product name or distribution
-	 *
-	 * @return					OS name
-	 */
-	chunk_t (*get_name)(os_info_t *this);
-
-	/**
-	 * Get the numeric OS version or release
-	 *
-	 * @param major				OS major version number
-	 * @param minor				OS minor version number
-	 */
-	void (*get_numeric_version)(os_info_t *this, u_int32_t *major,
-												 u_int32_t *minor);
-
-	/**
-	 * Get the OS version or release
-	 *
-	 * @return					OS version
-	 */
-	chunk_t (*get_version)(os_info_t *this);
-
-	/**
-	 * Get the OS IPv4 forwarding status
-	 *
-	 * @return					IP forwarding status
-	 */
-	os_fwd_status_t (*get_fwd_status)(os_info_t *this);
-
-	/**
-	 * Get the OS uptime in seconds
-	 *
-	 * @return					OS uptime
-	 */
-	time_t (*get_uptime)(os_info_t *this);
-
-	/**
-	 * Get an OS setting (restricted to /proc, /sys, and /etc)
-	 *
-	 * @param name				name of OS setting
-	 * @return					value of OS setting
-	 */
-	chunk_t (*get_setting)(os_info_t *this, char *name);
-
-	/**
-	 * Enumerates over all installed packages
-	 *
-	 * @return				return package enumerator
-	 */
-	enumerator_t* (*create_package_enumerator)(os_info_t *this);
-
-	/**
-	 * Destroys an os_info_t object.
-	 */
-	void (*destroy)(os_info_t *this);
-};
-
-/**
  * Convert an OS name into an OS enumeration type
  *
- * @param name				OS name
- * @return					OS enumeration type
+ * @param name							OS name
+ * @return								OS enumeration type
  */
 os_type_t os_type_from_name(chunk_t name);
 
-/**
- * Create an os_info_t object
- */
-os_info_t* os_info_create(void);
-
 #endif /** OS_INFO_H_ @}*/
diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.h b/src/libimcv/pa_tnc/pa_tnc_attr.h
index e2ce06e..1e0c339 100644
--- a/src/libimcv/pa_tnc/pa_tnc_attr.h
+++ b/src/libimcv/pa_tnc/pa_tnc_attr.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@ typedef struct pa_tnc_attr_t pa_tnc_attr_t;
 #include <library.h>
 #include <pen/pen.h>
 
+#define PA_TNC_ATTR_HEADER_SIZE		12
+
 /**
  * Interface for an RFC 5792 PA-TNC Posture Attribute.
  *
@@ -71,7 +73,7 @@ struct pa_tnc_attr_t {
 	 * @param					relative error offset within attribute body
 	 * @return					result status
 	 */
-	status_t (*process)(pa_tnc_attr_t *this, u_int32_t *offset);
+	status_t (*process)(pa_tnc_attr_t *this, uint32_t *offset);
 
 	/**
 	 * Get a new reference to the PA-TNC attribute
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c
index 140463b..77d383b 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.c
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
 #include <pen/pen.h>
 #include <utils/debug.h>
 
-
 typedef struct private_pa_tnc_msg_t private_pa_tnc_msg_t;
 
 /**
@@ -38,7 +37,6 @@ typedef struct private_pa_tnc_msg_t private_pa_tnc_msg_t;
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
-#define PA_TNC_HEADER_SIZE	8
 #define PA_TNC_RESERVED		0x000000
 
 /**
@@ -59,7 +57,6 @@ typedef struct private_pa_tnc_msg_t private_pa_tnc_msg_t;
 
 #define PA_TNC_ATTR_FLAG_NONE			0x00
 #define PA_TNC_ATTR_FLAG_NOSKIP			(1<<7)
-#define PA_TNC_ATTR_HEADER_SIZE			12
 #define PA_TNC_ATTR_INFO_SIZE			8
 
 /**
@@ -86,7 +83,7 @@ struct private_pa_tnc_msg_t {
 	/**
 	 * Message identifier
 	 */
-	u_int32_t identifier;
+	uint32_t identifier;
 
 	/**
 	 * Current PA-TNC Message size
@@ -139,13 +136,13 @@ METHOD(pa_tnc_msg_t, build, bool,
 	pa_tnc_attr_t *attr;
 	enum_name_t *pa_attr_names;
 	pen_type_t type;
-	u_int8_t flags;
+	uint8_t flags;
 	chunk_t value;
 	nonce_gen_t *ng;
 
 	/* generate a nonce as a message identifier */
 	ng = lib->crypto->create_nonce_gen(lib->crypto);
-	if (!ng || !ng->get_nonce(ng, 4, (u_int8_t*)&this->identifier))
+	if (!ng || !ng->get_nonce(ng, 4, (uint8_t*)&this->identifier))
 	{
 		DBG1(DBG_TNC, "failed to generate random PA-TNC message identifier");
 		DESTROY_IF(ng);
@@ -205,8 +202,8 @@ METHOD(pa_tnc_msg_t, process, status_t,
 {
 	bio_reader_t *reader;
 	pa_tnc_attr_t *error;
-	u_int8_t version;
-	u_int32_t reserved, offset, attr_offset;
+	uint8_t version;
+	uint32_t reserved, offset, attr_offset;
 	pen_type_t error_code = { PEN_IETF, PA_ERROR_INVALID_PARAMETER };
 
 	/* process message header */
@@ -237,8 +234,8 @@ METHOD(pa_tnc_msg_t, process, status_t,
 	while (reader->remaining(reader) >= PA_TNC_ATTR_HEADER_SIZE)
 	{
 		pen_t vendor_id;
-		u_int8_t flags;
-		u_int32_t type, length;
+		uint8_t flags;
+		uint32_t type, length;
 		chunk_t value, attr_info;
 		pa_tnc_attr_t *attr;
 		enum_name_t *pa_attr_names;
@@ -372,7 +369,7 @@ METHOD(pa_tnc_msg_t, process_ietf_std_errors, bool,
 			ietf_attr_pa_tnc_error_t *error_attr;
 			pen_type_t error_code;
 			chunk_t msg_info, attr_info;
-			u_int32_t offset;
+			uint32_t offset;
 
 			error_attr = (ietf_attr_pa_tnc_error_t*)attr;
 			error_code = error_attr->get_error_code(error_attr);
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h
index 218d3d6..84814b9 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.h
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 typedef struct pa_tnc_msg_t pa_tnc_msg_t;
 
 #define PA_TNC_VERSION		0x01
+#define PA_TNC_HEADER_SIZE	8
 
 #include "pa_tnc_attr.h"
 
diff --git a/src/libimcv/plugins/imc_os/Makefile.am b/src/libimcv/plugins/imc_os/Makefile.am
index fec38cd..e6dd10b 100644
--- a/src/libimcv/plugins/imc_os/Makefile.am
+++ b/src/libimcv/plugins/imc_os/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-os.la
 
diff --git a/src/libimcv/plugins/imc_os/Makefile.in b/src/libimcv/plugins/imc_os/Makefile.in
index 7b25614..2f0b854 100644
--- a/src/libimcv/plugins/imc_os/Makefile.in
+++ b/src/libimcv/plugins/imc_os/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -261,6 +261,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -279,6 +280,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -306,6 +308,7 @@ 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@
@@ -397,6 +400,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-os.la
 imc_os_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c
index 647a449..c624d26 100644
--- a/src/libimcv/plugins/imc_os/imc_os.c
+++ b/src/libimcv/plugins/imc_os/imc_os.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -17,6 +17,7 @@
 
 #include <imc/imc_agent.h>
 #include <imc/imc_msg.h>
+#include <imc/imc_os_info.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_attr_request.h>
 #include <ietf/ietf_attr_default_pwd_enabled.h>
@@ -31,7 +32,6 @@
 #include <ita/ita_attr_settings.h>
 #include <ita/ita_attr_angel.h>
 #include <ita/ita_attr_device_id.h>
-#include <os_info/os_info.h>
 
 #include <tncif_pa_subtypes.h>
 
@@ -47,15 +47,15 @@ static pen_type_t msg_types[] = {
 };
 
 static imc_agent_t *imc_os;
-static os_info_t *os;
+static imc_os_info_t *os;
 
 /**
  * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
-							  TNC_Version min_version,
-							  TNC_Version max_version,
-							  TNC_Version *actual_version)
+TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
+										  TNC_Version min_version,
+										  TNC_Version max_version,
+										  TNC_Version *actual_version)
 {
 	if (imc_os)
 	{
@@ -69,7 +69,7 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
 		return TNC_RESULT_FATAL;
 	}
 
-	os = os_info_create();
+	os = imc_os_info_create();
 	if (!os)
 	{
 		imc_os->destroy(imc_os);
@@ -89,9 +89,8 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
 /**
  * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
-										  TNC_ConnectionID connection_id,
-										  TNC_ConnectionState new_state)
+TNC_Result TNC_IMC_API TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
+				TNC_ConnectionID connection_id, TNC_ConnectionState new_state)
 {
 	imc_state_t *state;
 
@@ -238,23 +237,97 @@ static void add_default_pwd_enabled(imc_msg_t *msg)
 static void add_device_id(imc_msg_t *msg)
 {
 	pa_tnc_attr_t *attr;
-	chunk_t value;
-	char *name;
+	chunk_t value = chunk_empty, keyid;
+	char *name, *device_id, *cert_path;
+	certificate_t *cert = NULL;
+	public_key_t *pubkey;
+
+	/* Get the device ID as a character string */
+	device_id = lib->settings->get_str(lib->settings,
+						"%s.plugins.imc-os.device_id", NULL, lib->ns);
+	if (device_id)
+	{
+		value = chunk_clone(chunk_from_str(device_id));
+	}
+
+	if (value.len == 0)
+	{
+		/* Derive the device ID from a raw public key */
+		cert_path = lib->settings->get_str(lib->settings,
+							"%s.plugins.imc-os.device_pubkey", NULL, lib->ns);
+		if (cert_path)
+		{
+			cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+									  CERT_TRUSTED_PUBKEY, BUILD_FROM_FILE,
+									  cert_path, BUILD_END);
+			if (cert)
+			{
+				DBG2(DBG_IMC, "loaded device public key from '%s'", cert_path);
+			}
+			else
+			{
+				DBG1(DBG_IMC, "loading device public key from '%s' failed",
+							   cert_path);
+			}
+		}
+
+		if (!cert)
+		{
+			/* Derive the device ID from the public key contained in a certificate */
+			cert_path = lib->settings->get_str(lib->settings,
+								"%s.plugins.imc-os.device_cert", NULL, lib->ns);
+			if (cert_path)
+			{
+				cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+										  CERT_X509, BUILD_FROM_FILE,
+										  cert_path, BUILD_END);
+				if (cert)
+				{
+					DBG2(DBG_IMC, "loaded device certificate from '%s'", cert_path);
+				}
+				else
+				{
+					DBG1(DBG_IMC, "loading device certificate from '%s' failed",
+								   cert_path);
+				}
+			}
+		}
 
-	name = os->get_type(os) == OS_TYPE_ANDROID ?
-				  "android_id" : "/var/lib/dbus/machine-id";
-	value = os->get_setting(os, name);
+		/* Compute the SHA-1 keyid of the retrieved device public key */
+		if (cert)
+		{
+			pubkey = cert->get_public_key(cert);
+			if (pubkey)
+			{
+				if (pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_INFO_SHA1,
+											&keyid))
+				{
+					value = chunk_to_hex(keyid, NULL, FALSE);
+				}
+				pubkey->destroy(pubkey);
+			}
+			cert->destroy(cert);
+		}
+	}
 
 	if (value.len == 0)
 	{
-		DBG1(DBG_IMC, "no device ID available");
-		return;
+		/* Derive the device ID from some unique OS settings */
+		name = os->get_type(os) == OS_TYPE_ANDROID ?
+					  "android_id" : "/var/lib/dbus/machine-id";
+		value = os->get_setting(os, name);
+
+		/* Trim trailing newline character */
+		if (value.len > 0 && value.ptr[value.len - 1] == '\n')
+		{
+			value.len--;
+		}
 	}
 
-	/* trim trailing newline character */
-	if (value.ptr[value.len - 1] == '\n')
+	if (value.len == 0)
 	{
-		value.len--;
+		DBG1(DBG_IMC, "no device ID available");
+		return;
 	}
 
 	DBG1(DBG_IMC, "device ID is %.*s", value.len, value.ptr);
@@ -279,11 +352,12 @@ static void add_installed_packages(imc_state_t *state, imc_msg_t *msg)
 	 * Compute the maximum IETF Installed Packages attribute size
 	 * leaving space for an additional ITA Angel attribute
 	 */
-	max_attr_size = state->get_max_msg_len(state) - 8 - 12;
+	max_attr_size = state->get_max_msg_len(state) -
+					PA_TNC_HEADER_SIZE - PA_TNC_ATTR_HEADER_SIZE;
 
 	/* At least one IETF Installed Packages attribute is sent */
 	attr = ietf_attr_installed_packages_create();
-	attr_size = 12 + 4;
+	attr_size = PA_TNC_ATTR_HEADER_SIZE + IETF_INSTALLED_PACKAGES_MIN_SIZE;
 
 	enumerator = os->create_package_enumerator(os);
 	if (enumerator)
@@ -310,7 +384,8 @@ static void add_installed_packages(imc_state_t *state, imc_msg_t *msg)
 
 				/* create the next IETF Installed Packages attribute */
 				attr = ietf_attr_installed_packages_create();
-				attr_size = 12 + 4;
+				attr_size = PA_TNC_ATTR_HEADER_SIZE +
+							IETF_INSTALLED_PACKAGES_MIN_SIZE;
 			}
 			attr_cast = (ietf_attr_installed_packages_t*)attr;
 			attr_cast->add(attr_cast, name, version);
@@ -370,8 +445,8 @@ static void add_settings(enumerator_t *enumerator, imc_msg_t *msg)
 /**
  * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
-								  TNC_ConnectionID connection_id)
+TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
+											  TNC_ConnectionID connection_id)
 {
 	imc_state_t *state;
 	imc_msg_t *out_msg;
@@ -518,11 +593,11 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
  * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
 
  */
-TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
-								  TNC_ConnectionID connection_id,
-								  TNC_BufferReference msg,
-								  TNC_UInt32 msg_len,
-								  TNC_MessageType msg_type)
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
+											  TNC_ConnectionID connection_id,
+											  TNC_BufferReference msg,
+											  TNC_UInt32 msg_len,
+											  TNC_MessageType msg_type)
 {
 	imc_state_t *state;
 	imc_msg_t *in_msg;
@@ -548,15 +623,15 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
 /**
  * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
-									  TNC_ConnectionID connection_id,
-									  TNC_UInt32 msg_flags,
-									  TNC_BufferReference msg,
-									  TNC_UInt32 msg_len,
-									  TNC_VendorID msg_vid,
-									  TNC_MessageSubtype msg_subtype,
-									  TNC_UInt32 src_imv_id,
-									  TNC_UInt32 dst_imc_id)
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
+												  TNC_ConnectionID connection_id,
+												  TNC_UInt32 msg_flags,
+												  TNC_BufferReference msg,
+												  TNC_UInt32 msg_len,
+												  TNC_VendorID msg_vid,
+												  TNC_MessageSubtype msg_subtype,
+												  TNC_UInt32 src_imv_id,
+												  TNC_UInt32 dst_imc_id)
 {
 	imc_state_t *state;
 	imc_msg_t *in_msg;
@@ -583,8 +658,8 @@ TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
 /**
  * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
-							   TNC_ConnectionID connection_id)
+TNC_Result TNC_IMC_API TNC_IMC_BatchEnding(TNC_IMCID imc_id,
+										   TNC_ConnectionID connection_id)
 {
 	if (!imc_os)
 	{
@@ -597,7 +672,7 @@ TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
 /**
  * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
+TNC_Result TNC_IMC_API TNC_IMC_Terminate(TNC_IMCID imc_id)
 {
 	if (!imc_os)
 	{
@@ -616,8 +691,8 @@ TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
 /**
  * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
-									   TNC_TNCC_BindFunctionPointer bind_function)
+TNC_Result TNC_IMC_API TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
+									TNC_TNCC_BindFunctionPointer bind_function)
 {
 	if (!imc_os)
 	{
diff --git a/src/libimcv/plugins/imc_scanner/Makefile.am b/src/libimcv/plugins/imc_scanner/Makefile.am
index 7bf9075..44d3ad7 100644
--- a/src/libimcv/plugins/imc_scanner/Makefile.am
+++ b/src/libimcv/plugins/imc_scanner/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-scanner.la
 
diff --git a/src/libimcv/plugins/imc_scanner/Makefile.in b/src/libimcv/plugins/imc_scanner/Makefile.in
index afcaf1a..c66bb1a 100644
--- a/src/libimcv/plugins/imc_scanner/Makefile.in
+++ b/src/libimcv/plugins/imc_scanner/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -262,6 +262,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -280,6 +281,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -307,6 +309,7 @@ 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@
@@ -398,6 +401,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-scanner.la
 imc_scanner_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
diff --git a/src/libimcv/plugins/imc_test/Makefile.am b/src/libimcv/plugins/imc_test/Makefile.am
index 5a04f1f..4bdc234 100644
--- a/src/libimcv/plugins/imc_test/Makefile.am
+++ b/src/libimcv/plugins/imc_test/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-test.la
 
diff --git a/src/libimcv/plugins/imc_test/Makefile.in b/src/libimcv/plugins/imc_test/Makefile.in
index 1c30654..1702574 100644
--- a/src/libimcv/plugins/imc_test/Makefile.in
+++ b/src/libimcv/plugins/imc_test/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -261,6 +261,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -279,6 +280,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -306,6 +308,7 @@ 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@
@@ -397,6 +400,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-test.la
 imc_test_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
diff --git a/src/libimcv/plugins/imv_os/Makefile.am b/src/libimcv/plugins/imv_os/Makefile.am
index 434e26f..3b3f793 100644
--- a/src/libimcv/plugins/imv_os/Makefile.am
+++ b/src/libimcv/plugins/imv_os/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-os.la
 
@@ -18,9 +18,11 @@ imv_os_la_SOURCES = \
 
 imv_os_la_LDFLAGS = -module -avoid-version -no-undefined
 
+if !USE_WINDOWS
 ipsec_PROGRAMS = pacman
 pacman_SOURCES = pacman.c
 pacman_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 pacman.o :	$(top_builddir)/config.status
 
 EXTRA_DIST = pacman.sh
+endif
diff --git a/src/libimcv/plugins/imv_os/Makefile.in b/src/libimcv/plugins/imv_os/Makefile.in
index 0441750..cae6dbe 100644
--- a/src/libimcv/plugins/imv_os/Makefile.in
+++ b/src/libimcv/plugins/imv_os/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -79,7 +79,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-ipsec_PROGRAMS = pacman$(EXEEXT)
+ at USE_WINDOWS_FALSE@ipsec_PROGRAMS = pacman$(EXEEXT)
 subdir = src/libimcv/plugins/imv_os
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -142,10 +142,10 @@ imv_os_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(imv_os_la_LDFLAGS) $(LDFLAGS) -o $@
 PROGRAMS = $(ipsec_PROGRAMS)
-am_pacman_OBJECTS = pacman.$(OBJEXT)
+am__pacman_SOURCES_DIST = pacman.c
+ at USE_WINDOWS_FALSE@am_pacman_OBJECTS = pacman.$(OBJEXT)
 pacman_OBJECTS = $(am_pacman_OBJECTS)
-pacman_DEPENDENCIES =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+ at USE_WINDOWS_FALSE@pacman_DEPENDENCIES = $(top_builddir)/src/libstrongswan/libstrongswan.la
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -181,7 +181,7 @@ am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = $(imv_os_la_SOURCES) $(pacman_SOURCES)
-DIST_SOURCES = $(imv_os_la_SOURCES) $(pacman_SOURCES)
+DIST_SOURCES = $(imv_os_la_SOURCES) $(am__pacman_SOURCES_DIST)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -269,6 +269,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ 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@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-os.la
 imv_os_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
@@ -433,9 +437,9 @@ imv_os_la_SOURCES = \
 	imv_os_database.c imv_os_database.h
 
 imv_os_la_LDFLAGS = -module -avoid-version -no-undefined
-pacman_SOURCES = pacman.c
-pacman_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
-EXTRA_DIST = pacman.sh
+ at USE_WINDOWS_FALSE@pacman_SOURCES = pacman.c
+ at USE_WINDOWS_FALSE@pacman_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+ at USE_WINDOWS_FALSE@EXTRA_DIST = pacman.sh
 all: all-am
 
 .SUFFIXES:
@@ -812,7 +816,7 @@ uninstall-am: uninstall-imcvLTLIBRARIES uninstall-ipsecPROGRAMS
 	tags tags-am uninstall uninstall-am uninstall-imcvLTLIBRARIES \
 	uninstall-ipsecPROGRAMS
 
-pacman.o :	$(top_builddir)/config.status
+ at USE_WINDOWS_FALSE@pacman.o :	$(top_builddir)/config.status
 
 # 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.
diff --git a/src/libimcv/plugins/imv_os/imv_os_agent.c b/src/libimcv/plugins/imv_os/imv_os_agent.c
index 84a24b4..ca8bac6 100644
--- a/src/libimcv/plugins/imv_os/imv_os_agent.c
+++ b/src/libimcv/plugins/imv_os/imv_os_agent.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -118,23 +118,30 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
 		case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
 		case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
 		case TNC_CONNECTION_STATE_ACCESS_NONE:
-			if (imcv_db && this->agent->get_state(this->agent, id, &state))
+			if (this->agent->get_state(this->agent, id, &state) && imcv_db)
 			{
-				switch (new_state)
+				session = state->get_session(state);
+
+				if (session->get_policy_started(session))
 				{
-					case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
-						rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
-						break;
-					case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
-						rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
-						break;
-					case TNC_CONNECTION_STATE_ACCESS_NONE:
-					default:
-						rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+					switch (new_state)
+					{
+						case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+							rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+							break;
+						case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+							rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+							break;
+						case TNC_CONNECTION_STATE_ACCESS_NONE:
+						default:
+							rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+					}
+					imcv_db->add_recommendation(imcv_db, session, rec);
+					if (!imcv_db->policy_script(imcv_db, session, FALSE))
+					{
+						DBG1(DBG_IMV, "error in policy script stop");
+					}
 				}
-				session = state->get_session(state);
-				imcv_db->add_recommendation(imcv_db, session, rec);
-				imcv_db->policy_script(imcv_db, session, FALSE);
 			}
 			/* fall through to default state */
 		default:
@@ -150,6 +157,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
 {
 	imv_msg_t *out_msg;
 	imv_os_state_t *os_state;
+	imv_session_t *session;
+	imv_os_info_t *os_info = NULL;
 	enumerator_t *enumerator;
 	pa_tnc_attr_t *attr;
 	pen_type_t type;
@@ -159,6 +168,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
 	bool fatal_error = FALSE, assessment = FALSE;
 
 	os_state = (imv_os_state_t*)state;
+	session = state->get_session(state);
+	os_info = session->get_os_info(session);
 
 	/* parse received PA-TNC message and handle local and remote errors */
 	result = in_msg->receive(in_msg, &fatal_error);
@@ -188,6 +199,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
 											IMV_OS_ATTR_PRODUCT_INFORMATION);
 					attr_cast = (ietf_attr_product_info_t*)attr;
 					os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
+					os_info->set_name(os_info, os_name);
+
 					if (vendor_id != PEN_IETF)
 					{
 						DBG1(DBG_IMV, "operating system name is '%.*s' "
@@ -209,6 +222,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
 											IMV_OS_ATTR_STRING_VERSION);
 					attr_cast = (ietf_attr_string_version_t*)attr;
 					os_version = attr_cast->get_version(attr_cast, NULL, NULL);
+					os_info->set_version(os_info, os_version);
+
 					if (os_version.len)
 					{
 						DBG1(DBG_IMV, "operating system version is '%.*s'",
@@ -219,7 +234,7 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
 				case IETF_ATTR_NUMERIC_VERSION:
 				{
 					ietf_attr_numeric_version_t *attr_cast;
-					u_int32_t major, minor;
+					uint32_t major, minor;
 
 					state->set_action_flags(state,
 											IMV_OS_ATTR_NUMERIC_VERSION);
@@ -350,8 +365,8 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
 					state->set_action_flags(state, IMV_OS_ATTR_DEVICE_ID);
 
 					value = attr->get_value(attr);
-					os_state->set_device_id(os_state, value);
 					DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr);
+					session->set_device_id(session, value);
 					break;
 				}
 				case ITA_ATTR_START_ANGEL:
@@ -367,25 +382,6 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
 	}
 	enumerator->destroy(enumerator);
 
-	/**
-	 * The IETF Product Information and String Version attributes
-	 * are supposed to arrive in the same PA-TNC message
-	 */
-	if (os_name.len && os_version.len)
-	{
-		os_type_t os_type;
-
-		/* set the OS type, name and version */
-		os_type = os_type_from_name(os_name);
-		os_state->set_info(os_state,os_type, os_name, os_version);
-
-		if (imcv_db)
-		{
-			imcv_db->add_product(imcv_db, state->get_session(state),
-					os_state->get_info(os_state, NULL, NULL, NULL));
-		}
-	}
-
 	if (fatal_error)
 	{
 		state->set_recommendation(state,
@@ -457,7 +453,7 @@ METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
 /**
  * Build an IETF Attribute Request attribute for missing attributes
  */
-static pa_tnc_attr_t* build_attr_request(u_int32_t received)
+static pa_tnc_attr_t* build_attr_request(uint32_t received)
 {
 	pa_tnc_attr_t *attr;
 	ietf_attr_attr_request_t *attr_cast;
@@ -510,7 +506,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	TNC_Result result = TNC_RESULT_SUCCESS;
 	bool no_workitems = TRUE;
 	enumerator_t *enumerator;
-	u_int32_t received;
+	uint32_t received;
 
 	if (!this->agent->get_state(this->agent, id, &state))
 	{
@@ -542,56 +538,70 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 
 	if (handshake_state < IMV_OS_STATE_POLICY_START)
 	{
-		if (((received & IMV_OS_ATTR_PRODUCT_INFORMATION) &&
-			 (received & IMV_OS_ATTR_STRING_VERSION)) &&
-			((received & IMV_OS_ATTR_DEVICE_ID) ||
-			 (handshake_state == IMV_OS_STATE_ATTR_REQ)))
+		if (session->get_policy_started(session))
 		{
-			if (imcv_db)
+			/* the policy script has already been started by another IMV */
+			handshake_state = IMV_OS_STATE_POLICY_START;
+		}
+		else
+		{
+			if (((received & IMV_OS_ATTR_PRODUCT_INFORMATION) &&
+				 (received & IMV_OS_ATTR_STRING_VERSION)) &&
+				((received & IMV_OS_ATTR_DEVICE_ID) ||
+				 (handshake_state == IMV_OS_STATE_ATTR_REQ)))
 			{
-				imcv_db->add_device(imcv_db, session,
-								os_state->get_device_id(os_state));
-
-				/* trigger the policy manager */
-				imcv_db->policy_script(imcv_db, session, TRUE);
+				if (!session->get_device_id(session, NULL))
+				{
+					session->set_device_id(session, chunk_empty);
+				}
+				if (imcv_db)
+				{
+					/* start the policy script */
+					if (!imcv_db->policy_script(imcv_db, session, TRUE))
+					{
+						DBG1(DBG_IMV, "error in policy script start");
+					}
+				}
+				else
+				{
+					DBG2(DBG_IMV, "no workitems available - "
+								  "no evaluation possible");
+					state->set_recommendation(state,
+									TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+									TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+					session->set_policy_started(session, TRUE);
+				}
+				handshake_state = IMV_OS_STATE_POLICY_START;
 			}
-			else
+			else if (handshake_state == IMV_OS_STATE_ATTR_REQ)
 			{
-				DBG2(DBG_IMV, "no workitems available - no evaluation possible");
+				/**
+				 * both the IETF Product Information and IETF String Version
+				 * attribute should have been present
+				 */
 				state->set_recommendation(state,
-								TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
-								TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
-			}
-			handshake_state = IMV_OS_STATE_POLICY_START;
-		}
-		else if (handshake_state == IMV_OS_STATE_ATTR_REQ)
-		{
-			/**
-			 * both the IETF Product Information and IETF String Version
-			 * attribute should have been present
-			 */
-			state->set_recommendation(state,
 								TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
 								TNC_IMV_EVALUATION_RESULT_ERROR);
 
-			/* send assessment */
-			result = out_msg->send_assessment(out_msg);
-			out_msg->destroy(out_msg);
+				/* send assessment */
+				result = out_msg->send_assessment(out_msg);
+				out_msg->destroy(out_msg);
 
-			if (result != TNC_RESULT_SUCCESS)
+				if (result != TNC_RESULT_SUCCESS)
+				{
+					return result;
+				}  
+				return this->agent->provide_recommendation(this->agent, state);
+			}
+			else
 			{
-				return result;
-			}  
-			return this->agent->provide_recommendation(this->agent, state);
-		}
-		else
-		{
-			handshake_state = IMV_OS_STATE_ATTR_REQ;
+				handshake_state = IMV_OS_STATE_ATTR_REQ;
+			}
 		}
 		os_state->set_handshake_state(os_state, handshake_state);
 	}
 
-	if (handshake_state == IMV_OS_STATE_POLICY_START && session)
+	if (handshake_state == IMV_OS_STATE_POLICY_START)
 	{
 		enumerator = session->create_workitem_enumerator(session);
 		if (enumerator)
@@ -638,7 +648,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 		}
 	}
 
-	if (handshake_state == IMV_OS_STATE_WORKITEMS && session)
+	if (handshake_state == IMV_OS_STATE_WORKITEMS)
 	{
 		TNC_IMV_Evaluation_Result eval;
 		TNC_IMV_Action_Recommendation rec;
@@ -661,7 +671,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 					int count, count_update, count_blacklist, count_ok;
 
 					if (!(received & IMV_OS_ATTR_INSTALLED_PACKAGES) ||
-						os_state->get_angel_count(os_state))
+						os_state->get_angel_count(os_state) > 0)
 					{
 						continue;
 					}
@@ -672,7 +682,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 								  TNC_IMV_EVALUATION_RESULT_COMPLIANT;
 					snprintf(result_str, BUF_LEN, "processed %d packages: "
 							"%d not updated, %d blacklisted, %d ok, "
-							"%d not found",
+							"%d unknown",
 							count, count_update, count_blacklist, count_ok,
 							count - count_update - count_blacklist - count_ok);
 					break;
diff --git a/src/libimcv/plugins/imv_os/imv_os_database.c b/src/libimcv/plugins/imv_os/imv_os_database.c
index 12cf207..31b889b 100644
--- a/src/libimcv/plugins/imv_os/imv_os_database.c
+++ b/src/libimcv/plugins/imv_os/imv_os_database.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -41,41 +41,49 @@ struct private_imv_os_database_t {
 };
 
 METHOD(imv_os_database_t, check_packages, status_t,
-	private_imv_os_database_t *this, imv_os_state_t *state,
+	private_imv_os_database_t *this, imv_os_state_t *os_state,
 	enumerator_t *package_enumerator)
 {
+	imv_state_t *state;
+	imv_session_t *session;
+	imv_os_info_t *os_info;
+	os_type_t os_type;
 	char *product, *package, *release, *cur_release;
 	chunk_t name, version;
-	os_type_t os_type;
 	int pid, gid, security, blacklist;
 	int count = 0, count_ok = 0, count_no_match = 0, count_blacklist = 0;
 	enumerator_t *e;
 	status_t status = SUCCESS;
 	bool found, match;
 
-	product = state->get_info(state, &os_type, NULL, NULL);
+	state = &os_state->interface;
+	session = state->get_session(state);
+	session->get_session_id(session, &pid, NULL);
+	os_info = session->get_os_info(session);
+	os_type = os_info->get_type(os_info);
+	product = os_info->get_info(os_info);
 
 	if (os_type == OS_TYPE_ANDROID)
 	{
 		/*no package dependency on Android version */
 		product = enum_to_name(os_type_names, os_type);
-	}
-	DBG1(DBG_IMV, "processing installed '%s' packages", product);
 
-	/* Get primary key of product */
-	e = this->db->query(this->db,
-				"SELECT id FROM products WHERE name = ?",
-				DB_TEXT, product, DB_INT);
-	if (!e)
-	{
-		return FAILED;
-	}
-	if (!e->enumerate(e, &pid))
-	{
+		/* Get primary key of product */
+		e = this->db->query(this->db,
+					"SELECT id FROM products WHERE name = ?",
+					DB_TEXT, product, DB_INT);
+		if (!e)
+		{
+			return FAILED;
+		}
+		if (!e->enumerate(e, &pid))
+		{
+			e->destroy(e);
+			return NOT_FOUND;
+		}
 		e->destroy(e);
-		return NOT_FOUND;
 	}
-	e->destroy(e);
+	DBG1(DBG_IMV, "processing installed '%s' packages", product);
 
 	while (package_enumerator->enumerate(package_enumerator, &name, &version))
 	{
@@ -143,8 +151,8 @@ METHOD(imv_os_database_t, check_packages, status_t,
 					DBG2(DBG_IMV, "package '%s' (%s) is blacklisted",
 								   package, release);
 					count_blacklist++;
-					state->add_bad_package(state, package,
-										   OS_PACKAGE_STATE_BLACKLIST);
+					os_state->add_bad_package(os_state, package,
+											  OS_PACKAGE_STATE_BLACKLIST);
 				}
 				else
 				{
@@ -157,8 +165,8 @@ METHOD(imv_os_database_t, check_packages, status_t,
 			{
 				DBG1(DBG_IMV, "package '%s' (%s) no match", package, release);
 				count_no_match++;
-				state->add_bad_package(state, package,
-									   OS_PACKAGE_STATE_SECURITY);
+				os_state->add_bad_package(os_state, package,
+										  OS_PACKAGE_STATE_SECURITY);
 			}
 		}
 		else
@@ -168,22 +176,12 @@ METHOD(imv_os_database_t, check_packages, status_t,
 		free(package);
 		free(release);
 	}
-	state->set_count(state, count, count_no_match, count_blacklist, count_ok);
+	os_state->set_count(os_state, count, count_no_match,
+								  count_blacklist, count_ok);
 
 	return status;
 }
 
-METHOD(imv_os_database_t, set_device_info, void,
-	private_imv_os_database_t *this,  int session_id, int count,
-	int count_update, int count_blacklist, u_int flags)
-{
-	this->db->execute(this->db, NULL,
-			"INSERT INTO device_infos (session, count, count_update, "
-			"count_blacklist, flags) VALUES (?, ?, ?, ?, ?)",
-			 DB_INT, session_id, DB_INT, count, DB_INT, count_update,
-			 DB_INT, count_blacklist, DB_UINT, flags);
-}
-
 METHOD(imv_os_database_t, destroy, void,
 	private_imv_os_database_t *this)
 {
@@ -205,7 +203,6 @@ imv_os_database_t *imv_os_database_create(imv_database_t *imv_db)
 	INIT(this,
 		.public = {
 			.check_packages = _check_packages,
-			.set_device_info = _set_device_info,
 			.destroy = _destroy,
 		},
 		.db = imv_db->get_database(imv_db),
diff --git a/src/libimcv/plugins/imv_os/imv_os_database.h b/src/libimcv/plugins/imv_os/imv_os_database.h
index 7b9ef3c..9bf54fe 100644
--- a/src/libimcv/plugins/imv_os/imv_os_database.h
+++ b/src/libimcv/plugins/imv_os/imv_os_database.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -43,18 +43,6 @@ struct imv_os_database_t {
 							   enumerator_t *package_enumerator);
 
 	/**
-	 * Set health infos for a given  device
-	 *
-	 * @param sesson_id				Session ID
-	 * @param count					Number of installed packages
-	 * @param count_update			Number of packages to be updated
-	 * @param count_blacklist		Number of blacklisted packages
-	 * @param flags					Various flags, e.g. illegal OS settings
-	 */
-	void (*set_device_info)(imv_os_database_t *this, int session_id, int count,
-							int count_update, int count_blacklist, u_int flags);
-
-	/**
 	 * Destroys an imv_os_database_t object.
 	 */
 	void (*destroy)(imv_os_database_t *this);
diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c
index 4f5a4b0..dc8474a 100644
--- a/src/libimcv/plugins/imv_os/imv_os_state.c
+++ b/src/libimcv/plugins/imv_os/imv_os_state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
 #include "imv/imv_lang_string.h"
 #include "imv/imv_reason_string.h"
 #include "imv/imv_remediation_string.h"
+#include "imv/imv_os_info.h"
 
 #include <tncif_policy.h>
 
@@ -62,22 +63,12 @@ struct private_imv_os_state_t {
 	/**
 	 * Maximum PA-TNC message size for this TNCCS connection
 	 */
-	u_int32_t max_msg_len;
+	uint32_t max_msg_len;
 
 	/**
 	 * Flags set for completed actions
 	 */
-	u_int32_t action_flags;
-
-	/**
-	 * Access Requestor ID Type
-	 */
-	u_int32_t ar_id_type;
-
-	/**
-	 * Access Requestor ID Value
-	 */
-	chunk_t ar_id_value;
+	uint32_t action_flags;
 
 	/**
 	 * IMV database session associated with TNCCS connection
@@ -100,32 +91,12 @@ struct private_imv_os_state_t {
 	imv_os_handshake_state_t handshake_state;
 
 	/**
-	 * OS Product Information (concatenation of OS Name and Version)
-	 */
-	char *info;
-
-	/**
-	 * OS Type
-	 */
-	os_type_t type;
-
-	/**
-	 * OS Name
-	 */
-	chunk_t name;
-
-	/**
-	 * OS Version
-	 */
-	chunk_t version;
-
-	/**
 	 * List of blacklisted packages to be removed
 	 */
 	linked_list_t *remove_packages;
 
 	/**
-	 * List of vulnerable packages to be updated
+	 h* List of vulnerable packages to be updated
 	 */
 	linked_list_t *update_packages;
 
@@ -140,11 +111,6 @@ struct private_imv_os_state_t {
 	imv_remediation_string_t *remediation_string;
 
 	/**
-	 * Dgevice ID
-	 */
-	chunk_t device_id;
-
-	/**
 	 * Number of processed packages
 	 */
 	int count;
@@ -326,46 +292,29 @@ METHOD(imv_state_t, set_flags, void,
 }
 
 METHOD(imv_state_t, set_max_msg_len, void,
-	private_imv_os_state_t *this, u_int32_t max_msg_len)
+	private_imv_os_state_t *this, uint32_t max_msg_len)
 {
 	this->max_msg_len = max_msg_len;
 }
 
-METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
 	private_imv_os_state_t *this)
 {
 	return this->max_msg_len;
 }
 
 METHOD(imv_state_t, set_action_flags, void,
-	private_imv_os_state_t *this, u_int32_t flags)
+	private_imv_os_state_t *this, uint32_t flags)
 {
 	this->action_flags |= flags;
 }
 
-METHOD(imv_state_t, get_action_flags, u_int32_t,
+METHOD(imv_state_t, get_action_flags, uint32_t,
 	private_imv_os_state_t *this)
 {
 	return this->action_flags;
 }
 
-METHOD(imv_state_t, set_ar_id, void,
-	private_imv_os_state_t *this, u_int32_t id_type, chunk_t id_value)
-{
-	this->ar_id_type = id_type;
-	this->ar_id_value = chunk_clone(id_value);
-}
-
-METHOD(imv_state_t, get_ar_id, chunk_t,
-	private_imv_os_state_t *this, u_int32_t *id_type)
-{
-	if (id_type)
-	{
-		*id_type = this->ar_id_type;
-	}
-	return this->ar_id_value;
-}
-
 METHOD(imv_state_t, set_session, void,
 	private_imv_os_state_t *this, imv_session_t *session)
 {
@@ -440,6 +389,9 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
 	private_imv_os_state_t *this, enumerator_t *language_enumerator,
 	chunk_t *string, char **lang_code, char **uri)
 {
+	imv_os_info_t *os_info;
+	bool as_xml = FALSE;
+
 	if (!this->count_update && !this->count_blacklist & !this->os_settings)
 	{
 		return FALSE;
@@ -449,8 +401,12 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
 
 	/* Instantiate an IETF Remediation Instructions String object */
 	DESTROY_IF(this->remediation_string);
-	this->remediation_string = imv_remediation_string_create(
-									this->type == OS_TYPE_ANDROID, *lang_code);
+	if (this->session)
+	{
+		os_info = this->session->get_os_info(this->session);
+		as_xml = os_info->get_type(os_info) == OS_TYPE_ANDROID;
+	}
+	this->remediation_string = imv_remediation_string_create(as_xml, *lang_code);
 
 	/* List of blacklisted packages to be removed, if any */
 	if (this->count_blacklist)
@@ -507,11 +463,6 @@ METHOD(imv_state_t, destroy, void,
 	DESTROY_IF(this->remediation_string);
 	this->update_packages->destroy_function(this->update_packages, free);
 	this->remove_packages->destroy_function(this->remove_packages, free);
-	free(this->info);
-	free(this->name.ptr);
-	free(this->version.ptr);
-	free(this->ar_id_value.ptr);
-	free(this->device_id.ptr);
 	free(this);
 }
 
@@ -527,39 +478,6 @@ METHOD(imv_os_state_t, get_handshake_state, imv_os_handshake_state_t,
 	return this->handshake_state;
 }
 
-METHOD(imv_os_state_t, set_info, void,
-	private_imv_os_state_t *this, os_type_t type, chunk_t name, chunk_t version)
-{
-	int len = name.len + 1 + version.len + 1;
-
-	/* OS info is a concatenation of OS name and OS version */
-	free(this->info);
-	this->info = malloc(len);
-	snprintf(this->info, len, "%.*s %.*s", (int)name.len, name.ptr,
-										   (int)version.len, version.ptr);
-	this->type = type;
-	this->name = chunk_clone(name);
-	this->version = chunk_clone(version);
-}
-
-METHOD(imv_os_state_t, get_info, char*,
-	private_imv_os_state_t *this, os_type_t *type, chunk_t *name,
-	chunk_t *version)
-{
-	if (type)
-	{
-		*type = this->type;
-	}
-	if (name)
-	{
-		*name = this->name;
-	}
-	if (version)
-	{
-		*version = this->version;
-	}
-	return this->info;
-}
 
 METHOD(imv_os_state_t, set_count, void,
 	private_imv_os_state_t *this, int count, int count_update,
@@ -593,18 +511,6 @@ METHOD(imv_os_state_t, get_count, void,
 	}
 }
 
-METHOD(imv_os_state_t, set_device_id, void,
-	private_imv_os_state_t *this, chunk_t id)
-{
-	this->device_id = chunk_clone(id);
-}
-
-METHOD(imv_os_state_t, get_device_id, chunk_t,
-	private_imv_os_state_t *this)
-{
-	return this->device_id;
-}
-
 METHOD(imv_os_state_t, set_os_settings, void,
 	private_imv_os_state_t *this, u_int settings)
 {
@@ -663,8 +569,6 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
 				.get_max_msg_len = _get_max_msg_len,
 				.set_action_flags = _set_action_flags,
 				.get_action_flags = _get_action_flags,
-				.set_ar_id = _set_ar_id,
-				.get_ar_id = _get_ar_id,
 				.set_session = _set_session,
 				.get_session = _get_session,
 				.change_state = _change_state,
@@ -677,12 +581,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
 			},
 			.set_handshake_state = _set_handshake_state,
 			.get_handshake_state = _get_handshake_state,
-			.set_info = _set_info,
-			.get_info = _get_info,
 			.set_count = _set_count,
 			.get_count = _get_count,
-			.set_device_id = _set_device_id,
-			.get_device_id = _get_device_id,
 			.set_os_settings = _set_os_settings,
 			.get_os_settings = _get_os_settings,
 			.set_angel_count = _set_angel_count,
diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h
index 97f6953..82ebb6c 100644
--- a/src/libimcv/plugins/imv_os/imv_os_state.h
+++ b/src/libimcv/plugins/imv_os/imv_os_state.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -78,27 +78,6 @@ struct imv_os_state_t {
 	imv_os_handshake_state_t (*get_handshake_state)(imv_os_state_t *this);
 
 	/**
-	 * Set OS Product Information
-	 *
-	 * @param type			OS type (enumerated)
-	 * @param name			OS name (string)
-	 * @param version		OS version
-	 */
-	void (*set_info)(imv_os_state_t *this, os_type_t os_type,
-					 chunk_t name, chunk_t version);
-
-	/**
-	 * Get OS Product Information
-	 *
-	 * @param type			OS type (enumerated)
-	 * @param name			OS name (string)
-	 * @param version		OS version
-	 * @return				OS name & version as a concatenated string
-	 */
-	char* (*get_info)(imv_os_state_t *this, os_type_t *os_type,
-					  chunk_t *name, chunk_t *version);
-
-	/**
 	 * Set [or with multiple attributes increment] package counters
 	 *
 	 * @param count				Number of processed packages
@@ -121,20 +100,6 @@ struct imv_os_state_t {
 					  int *count_blacklist, int *count_ok);
 
 	/**
-	 * Set device ID
-	 *
-	 * @param device_id		Device ID
-	 */
-	void (*set_device_id)(imv_os_state_t *this, chunk_t id);
-
-	/**
-	 * Get device ID
-	 *
-	 * @return				Device ID
-	 */
-	chunk_t (*get_device_id)(imv_os_state_t *this);
-
-	/**
 	 * Set OS settings
 	 *
 	 * @param settings		OS settings
diff --git a/src/libimcv/plugins/imv_os/pacman.sh b/src/libimcv/plugins/imv_os/pacman.sh
index 3dfea39..fcf35b6 100755
--- a/src/libimcv/plugins/imv_os/pacman.sh
+++ b/src/libimcv/plugins/imv_os/pacman.sh
@@ -3,7 +3,7 @@
 DIR="/etc/pts"
 DATE=`date +%Y%m%d-%H%M`
 UBUNTU="http://security.ubuntu.com/ubuntu/dists"
-UBUNTU_VERSIONS="saucy raring quantal precise lucid"
+UBUNTU_VERSIONS="trusty saucy raring quantal precise lucid"
 UBUNTU_DIRS="main multiverse restricted universe"
 UBUNTU_ARCH="binary-amd64 binary-i386"
 DEBIAN="http://security.debian.org/dists"
@@ -44,6 +44,27 @@ do
   done
 done
 
+for f in trusty-security/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 14.04 x86_64" --file $f --security >> $PACMAN_LOG
+done
+echo
+for f in trusty-updates/binary-amd64/*
+do
+  $PACMAN --product "Ubuntu 14.04 x86_64" --file $f >> $PACMAN_LOG
+done
+echo
+for f in trusty-security/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 14.04 i686" --file $f --security >> $PACMAN_LOG
+done
+echo
+for f in trusty-updates/binary-i386/*
+do
+  $PACMAN --product "Ubuntu 14.04 i686" --file $f >> $PACMAN_LOG
+done
+echo
+
 for f in saucy-security/binary-amd64/*
 do
   $PACMAN --product "Ubuntu 13.10 x86_64" --file $f --security >> $PACMAN_LOG
diff --git a/src/libimcv/plugins/imv_scanner/Makefile.am b/src/libimcv/plugins/imv_scanner/Makefile.am
index 2bb0d67..9881443 100644
--- a/src/libimcv/plugins/imv_scanner/Makefile.am
+++ b/src/libimcv/plugins/imv_scanner/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-scanner.la
 
diff --git a/src/libimcv/plugins/imv_scanner/Makefile.in b/src/libimcv/plugins/imv_scanner/Makefile.in
index 525f445..18446e7 100644
--- a/src/libimcv/plugins/imv_scanner/Makefile.in
+++ b/src/libimcv/plugins/imv_scanner/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-scanner.la
 imv_scanner_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c b/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
index d1e0931..85ef23b 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
@@ -259,7 +259,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
 							 msg_types[0]);
 
-	if (!session)
+	if (!imcv_db)
 	{
 		DBG2(DBG_IMV, "no workitems available - no evaluation possible");
 		state->set_recommendation(state,
@@ -276,7 +276,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 		return this->agent->provide_recommendation(this->agent, state);
 	}
 
-	if (handshake_state == IMV_SCANNER_STATE_INIT)
+	if (handshake_state == IMV_SCANNER_STATE_INIT &&
+		session->get_policy_started(session))
 	{
 		enumerator = session->create_workitem_enumerator(session);
 		if (enumerator)
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
index 90475d3..24a49a7 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -58,22 +58,12 @@ struct private_imv_scanner_state_t {
 	/**
 	 * Maximum PA-TNC message size for this TNCCS connection
 	 */
-	u_int32_t max_msg_len;
+	uint32_t max_msg_len;
 
 	/**
 	 * Flags set for completed actions
 	 */
-	u_int32_t action_flags;
-
-	/**
-	 * Access Requestor ID Type
-	 */
-	u_int32_t ar_id_type;
-
-	/**
-	 * Access Requestor ID Value
-	 */
-	chunk_t ar_id_value;
+	uint32_t action_flags;
 
 	/**
 	 * IMV database session associatied with TNCCS connection
@@ -186,46 +176,29 @@ METHOD(imv_state_t, set_flags, void,
 }
 
 METHOD(imv_state_t, set_max_msg_len, void,
-	private_imv_scanner_state_t *this, u_int32_t max_msg_len)
+	private_imv_scanner_state_t *this, uint32_t max_msg_len)
 {
 	this->max_msg_len = max_msg_len;
 }
 
-METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
 	private_imv_scanner_state_t *this)
 {
 	return this->max_msg_len;
 }
 
 METHOD(imv_state_t, set_action_flags, void,
-	private_imv_scanner_state_t *this, u_int32_t flags)
+	private_imv_scanner_state_t *this, uint32_t flags)
 {
 	this->action_flags |= flags;
 }
 
-METHOD(imv_state_t, get_action_flags, u_int32_t,
+METHOD(imv_state_t, get_action_flags, uint32_t,
 	private_imv_scanner_state_t *this)
 {
 	return this->action_flags;
 }
 
-METHOD(imv_state_t, set_ar_id, void,
-	private_imv_scanner_state_t *this, u_int32_t id_type, chunk_t id_value)
-{
-	this->ar_id_type = id_type;
-	this->ar_id_value = chunk_clone(id_value);
-}
-
-METHOD(imv_state_t, get_ar_id, chunk_t,
-	private_imv_scanner_state_t *this, u_int32_t *id_type)
-{
-	if (id_type)
-	{
-		*id_type = this->ar_id_type;
-	}
-	return this->ar_id_value;
-}
-
 METHOD(imv_state_t, set_session, void,
 	private_imv_scanner_state_t *this, imv_session_t *session)
 {
@@ -327,7 +300,6 @@ METHOD(imv_state_t, destroy, void,
 	DESTROY_IF(this->remediation_string);
 	DESTROY_IF(&this->port_filter_attr->pa_tnc_attribute);
 	this->violating_ports->destroy_function(this->violating_ports, free);
-	free(this->ar_id_value.ptr);
 	free(this);
 }
 
@@ -380,8 +352,6 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID connection_id)
 				.get_max_msg_len = _get_max_msg_len,
 				.set_action_flags = _set_action_flags,
 				.get_action_flags = _get_action_flags,
-				.set_ar_id = _set_ar_id,
-				.get_ar_id = _get_ar_id,
 				.set_session = _set_session,
 				.get_session= _get_session,
 				.change_state = _change_state,
diff --git a/src/libimcv/plugins/imv_test/Makefile.am b/src/libimcv/plugins/imv_test/Makefile.am
index 5ed9161..4fe715f 100644
--- a/src/libimcv/plugins/imv_test/Makefile.am
+++ b/src/libimcv/plugins/imv_test/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-test.la
 
diff --git a/src/libimcv/plugins/imv_test/Makefile.in b/src/libimcv/plugins/imv_test/Makefile.in
index 3724cc5..5ac6a8f 100644
--- a/src/libimcv/plugins/imv_test/Makefile.in
+++ b/src/libimcv/plugins/imv_test/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -262,6 +262,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -280,6 +281,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -307,6 +309,7 @@ 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@
@@ -398,6 +401,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libimcv
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-test.la
 imv_test_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
diff --git a/src/libimcv/plugins/imv_test/imv_test_state.c b/src/libimcv/plugins/imv_test/imv_test_state.c
index f05db80..3564456 100644
--- a/src/libimcv/plugins/imv_test/imv_test_state.c
+++ b/src/libimcv/plugins/imv_test/imv_test_state.c
@@ -58,17 +58,7 @@ struct private_imv_test_state_t {
 	/**
 	 * Maximum PA-TNC message size for this TNCCS connection
 	 */
-	u_int32_t max_msg_len;
-
-	/**
-	 * Access Requestor ID Type
-	 */
-	u_int32_t ar_id_type;
-
-	/**
-	 * Access Requestor ID Value
-	 */
-	chunk_t ar_id_value;
+	uint32_t max_msg_len;
 
 	/**
 	 * IMV database session associated with TNCCS connection
@@ -149,34 +139,17 @@ METHOD(imv_state_t, set_flags, void,
 }
 
 METHOD(imv_state_t, set_max_msg_len, void,
-	private_imv_test_state_t *this, u_int32_t max_msg_len)
+	private_imv_test_state_t *this, uint32_t max_msg_len)
 {
 	this->max_msg_len = max_msg_len;
 }
 
-METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
 	private_imv_test_state_t *this)
 {
 	return this->max_msg_len;
 }
 
-METHOD(imv_state_t, set_ar_id, void,
-	private_imv_test_state_t *this, u_int32_t id_type, chunk_t id_value)
-{
-	this->ar_id_type = id_type;
-	this->ar_id_value = chunk_clone(id_value);
-}
-
-METHOD(imv_state_t, get_ar_id, chunk_t,
-	private_imv_test_state_t *this, u_int32_t *id_type)
-{
-	if (id_type)
-	{
-		*id_type = this->ar_id_type;
-	}
-	return this->ar_id_value;
-}
-
 METHOD(imv_state_t, set_session, void,
 	private_imv_test_state_t *this, imv_session_t *session)
 {
@@ -248,7 +221,6 @@ METHOD(imv_state_t, destroy, void,
 	DESTROY_IF(this->session);
 	DESTROY_IF(this->reason_string);
 	this->imcs->destroy_function(this->imcs, free);
-	free(this->ar_id_value.ptr);
 	free(this);
 }
 
@@ -333,8 +305,6 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
 				.set_flags = _set_flags,
 				.set_max_msg_len = _set_max_msg_len,
 				.get_max_msg_len = _get_max_msg_len,
-				.set_ar_id = _set_ar_id,
-				.get_ar_id = _get_ar_id,
 				.set_session = _set_session,
 				.get_session = _get_session,
 				.change_state = _change_state,
diff --git a/src/libipsec/Makefile.in b/src/libipsec/Makefile.in
index f1a099e..31494ed 100644
--- a/src/libipsec/Makefile.in
+++ b/src/libipsec/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -303,6 +303,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -321,6 +322,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -348,6 +350,7 @@ 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@
@@ -439,6 +442,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/libipsec/esp_packet.c b/src/libipsec/esp_packet.c
index ebe13ce..8223022 100644
--- a/src/libipsec/esp_packet.c
+++ b/src/libipsec/esp_packet.c
@@ -115,7 +115,7 @@ METHOD(packet_t, skip_bytes, void,
 	return this->packet->skip_bytes(this->packet, bytes);
 }
 
-METHOD(packet_t, clone, packet_t*,
+METHOD(packet_t, clone_, packet_t*,
 	private_esp_packet_t *this)
 {
 	private_esp_packet_t *pkt;
@@ -414,7 +414,7 @@ static private_esp_packet_t *esp_packet_create_internal(packet_t *packet)
 				.get_dscp = _get_dscp,
 				.set_dscp = _set_dscp,
 				.skip_bytes = _skip_bytes,
-				.clone = _clone,
+				.clone = _clone_,
 				.destroy = _destroy,
 			},
 			.get_source = _get_source,
diff --git a/src/libipsec/ip_packet.c b/src/libipsec/ip_packet.c
index ede9d10..181cb88 100644
--- a/src/libipsec/ip_packet.c
+++ b/src/libipsec/ip_packet.c
@@ -95,7 +95,7 @@ METHOD(ip_packet_t, get_next_header, u_int8_t,
 	return this->next_header;
 }
 
-METHOD(ip_packet_t, clone, ip_packet_t*,
+METHOD(ip_packet_t, clone_, ip_packet_t*,
 	private_ip_packet_t *this)
 {
 	return ip_packet_create(chunk_clone(this->packet));
@@ -183,7 +183,7 @@ ip_packet_t *ip_packet_create(chunk_t packet)
 			.get_destination = _get_destination,
 			.get_next_header = _get_next_header,
 			.get_encoding = _get_encoding,
-			.clone = _clone,
+			.clone = _clone_,
 			.destroy = _destroy,
 		},
 		.src = src,
diff --git a/src/libipsec/ipsec_policy_mgr.c b/src/libipsec/ipsec_policy_mgr.c
index 02dc59d..e2eaba0 100644
--- a/src/libipsec/ipsec_policy_mgr.c
+++ b/src/libipsec/ipsec_policy_mgr.c
@@ -22,7 +22,7 @@
 #include <collections/linked_list.h>
 
 /** Base priority for installed policies */
-#define PRIO_BASE 512
+#define PRIO_BASE 384
 
 typedef struct private_ipsec_policy_mgr_t private_ipsec_policy_mgr_t;
 
@@ -88,6 +88,9 @@ static u_int32_t calculate_priority(policy_priority_t policy_priority,
 			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 */
diff --git a/src/libpts/Android.mk b/src/libpts/Android.mk
new file mode 100644
index 0000000..ce328c5
--- /dev/null
+++ b/src/libpts/Android.mk
@@ -0,0 +1,78 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+libpts_la_SOURCES := \
+	libpts.h libpts.c \
+	pts/pts.h pts/pts.c \
+	pts/pts_error.h pts/pts_error.c \
+	pts/pts_pcr.h pts/pts_pcr.c \
+	pts/pts_proto_caps.h \
+	pts/pts_req_func_comp_evid.h \
+	pts/pts_simple_evid_final.h \
+	pts/pts_creds.h pts/pts_creds.c \
+	pts/pts_database.h pts/pts_database.c \
+	pts/pts_dh_group.h pts/pts_dh_group.c \
+	pts/pts_file_meas.h pts/pts_file_meas.c \
+	pts/pts_file_meta.h pts/pts_file_meta.c \
+	pts/pts_file_type.h pts/pts_file_type.c \
+	pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+	pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
+	pts/pts_meas_algo.h pts/pts_meas_algo.c \
+	pts/components/pts_component.h \
+	pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
+	pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
+	pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
+	pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
+	pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
+	pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
+	pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
+	pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+	swid/swid_error.h swid/swid_error.c \
+	swid/swid_inventory.h swid/swid_inventory.c \
+	swid/swid_tag.h swid/swid_tag.c \
+	swid/swid_tag_id.h swid/swid_tag_id.c \
+	tcg/tcg_attr.h tcg/tcg_attr.c \
+	tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
+	tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
+	tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
+	tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
+	tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
+	tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
+	tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
+	tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
+	tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
+	tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
+	tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
+	tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
+	tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
+	tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
+	tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
+	tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
+	tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
+	tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
+	tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
+	tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
+
+LOCAL_SRC_FILES := $(filter %.c,$(libpts_la_SOURCES))
+
+# build libpts -----------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+	$(strongswan_PATH)/src/libtncif \
+	$(strongswan_PATH)/src/libimcv \
+	$(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := libpts
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan libimcv
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/src/libpts/Makefile.am b/src/libpts/Makefile.am
index 48bb46c..ea685d8 100644
--- a/src/libpts/Makefile.am
+++ b/src/libpts/Makefile.am
@@ -13,6 +13,10 @@ libpts_la_LIBADD = \
 	$(top_builddir)/src/libtncif/libtncif.la \
 	$(top_builddir)/src/libimcv/libimcv.la
 
+if USE_WINDOWS
+  libpts_la_LIBADD += -lws2_32
+endif
+
 if USE_TROUSERS
   libpts_la_LIBADD += -ltspi
 endif
@@ -31,6 +35,8 @@ libpts_la_SOURCES = \
 	pts/pts_file_meas.h pts/pts_file_meas.c \
 	pts/pts_file_meta.h pts/pts_file_meta.c \
 	pts/pts_file_type.h pts/pts_file_type.c \
+	pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+	pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
 	pts/pts_meas_algo.h pts/pts_meas_algo.c \
 	pts/components/pts_component.h \
 	pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
@@ -67,6 +73,8 @@ libpts_la_SOURCES = \
 	tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
 	tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
 
+EXTRA_DIST = Android.mk
+
 SUBDIRS = .
 
 if USE_IMC_ATTESTATION
diff --git a/src/libpts/Makefile.in b/src/libpts/Makefile.in
index af5eafd..405b5f7 100644
--- a/src/libpts/Makefile.in
+++ b/src/libpts/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -78,11 +78,12 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at USE_TROUSERS_TRUE@am__append_1 = -ltspi
- at USE_IMC_ATTESTATION_TRUE@am__append_2 = plugins/imc_attestation
- at USE_IMV_ATTESTATION_TRUE@am__append_3 = plugins/imv_attestation
- at USE_IMC_SWID_TRUE@am__append_4 = plugins/imc_swid
- at USE_IMV_SWID_TRUE@am__append_5 = plugins/imv_swid
+ at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
+ at USE_TROUSERS_TRUE@am__append_2 = -ltspi
+ at USE_IMC_ATTESTATION_TRUE@am__append_3 = plugins/imc_attestation
+ at USE_IMV_ATTESTATION_TRUE@am__append_4 = plugins/imv_attestation
+ at USE_IMC_SWID_TRUE@am__append_5 = plugins/imc_swid
+ at USE_IMV_SWID_TRUE@am__append_6 = plugins/imv_swid
 subdir = src/libpts
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -136,12 +137,14 @@ am__DEPENDENCIES_1 =
 libpts_la_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libtncif/libtncif.la \
-	$(top_builddir)/src/libimcv/libimcv.la $(am__DEPENDENCIES_1)
+	$(top_builddir)/src/libimcv/libimcv.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 am__dirstamp = $(am__leading_dot)dirstamp
 am_libpts_la_OBJECTS = libpts.lo pts/pts.lo pts/pts_error.lo \
 	pts/pts_pcr.lo pts/pts_creds.lo pts/pts_database.lo \
 	pts/pts_dh_group.lo pts/pts_file_meas.lo pts/pts_file_meta.lo \
-	pts/pts_file_type.lo pts/pts_meas_algo.lo \
+	pts/pts_file_type.lo pts/pts_ima_bios_list.lo \
+	pts/pts_ima_event_list.lo pts/pts_meas_algo.lo \
 	pts/components/pts_component_manager.lo \
 	pts/components/pts_comp_evidence.lo \
 	pts/components/pts_comp_func_name.lo \
@@ -341,6 +344,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -359,6 +363,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -386,6 +391,7 @@ 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@
@@ -477,6 +483,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -498,7 +505,8 @@ AM_LDFLAGS = \
 ipseclib_LTLIBRARIES = libpts.la
 libpts_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libtncif/libtncif.la \
-	$(top_builddir)/src/libimcv/libimcv.la $(am__append_1)
+	$(top_builddir)/src/libimcv/libimcv.la $(am__append_1) \
+	$(am__append_2)
 libpts_la_SOURCES = \
 	libpts.h libpts.c \
 	pts/pts.h pts/pts.c \
@@ -513,6 +521,8 @@ libpts_la_SOURCES = \
 	pts/pts_file_meas.h pts/pts_file_meas.c \
 	pts/pts_file_meta.h pts/pts_file_meta.c \
 	pts/pts_file_type.h pts/pts_file_type.c \
+	pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
+	pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
 	pts/pts_meas_algo.h pts/pts_meas_algo.c \
 	pts/components/pts_component.h \
 	pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
@@ -549,8 +559,9 @@ libpts_la_SOURCES = \
 	tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
 	tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
 
-SUBDIRS = . $(am__append_2) $(am__append_3) $(am__append_4) \
-	$(am__append_5)
+EXTRA_DIST = Android.mk
+SUBDIRS = . $(am__append_3) $(am__append_4) $(am__append_5) \
+	$(am__append_6)
 all: all-recursive
 
 .SUFFIXES:
@@ -638,6 +649,10 @@ pts/pts_file_meta.lo: pts/$(am__dirstamp) \
 	pts/$(DEPDIR)/$(am__dirstamp)
 pts/pts_file_type.lo: pts/$(am__dirstamp) \
 	pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_ima_bios_list.lo: pts/$(am__dirstamp) \
+	pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_ima_event_list.lo: pts/$(am__dirstamp) \
+	pts/$(DEPDIR)/$(am__dirstamp)
 pts/pts_meas_algo.lo: pts/$(am__dirstamp) \
 	pts/$(DEPDIR)/$(am__dirstamp)
 pts/components/$(am__dirstamp):
@@ -787,6 +802,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at pts/$(DEPDIR)/pts_file_meas.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at pts/$(DEPDIR)/pts_file_meta.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at pts/$(DEPDIR)/pts_file_type.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at pts/$(DEPDIR)/pts_ima_bios_list.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at pts/$(DEPDIR)/pts_ima_event_list.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at pts/$(DEPDIR)/pts_meas_algo.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at pts/$(DEPDIR)/pts_pcr.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at pts/components/$(DEPDIR)/pts_comp_evidence.Plo at am__quote@
diff --git a/src/libpts/plugins/imc_attestation/Makefile.am b/src/libpts/plugins/imc_attestation/Makefile.am
index 3f1b52a..88d9ddd 100644
--- a/src/libpts/plugins/imc_attestation/Makefile.am
+++ b/src/libpts/plugins/imc_attestation/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libpts
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-attestation.la
 
diff --git a/src/libpts/plugins/imc_attestation/Makefile.in b/src/libpts/plugins/imc_attestation/Makefile.in
index dd347d2..1f12af6 100644
--- a/src/libpts/plugins/imc_attestation/Makefile.in
+++ b/src/libpts/plugins/imc_attestation/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libpts
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-attestation.la
 imc_attestation_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation.c b/src/libpts/plugins/imc_attestation/imc_attestation.c
index c71b216..74bbc46 100644
--- a/src/libpts/plugins/imc_attestation/imc_attestation.c
+++ b/src/libpts/plugins/imc_attestation/imc_attestation.c
@@ -61,10 +61,10 @@ static pts_dh_group_t supported_dh_groups = PTS_DH_GROUP_NONE;
 /**
  * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
-							  TNC_Version min_version,
-							  TNC_Version max_version,
-							  TNC_Version *actual_version)
+TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
+										  TNC_Version min_version,
+										  TNC_Version max_version,
+										  TNC_Version *actual_version)
 {
 	bool mandatory_dh_groups;
 
@@ -103,9 +103,9 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
 /**
  * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
-										  TNC_ConnectionID connection_id,
-										  TNC_ConnectionState new_state)
+TNC_Result TNC_IMC_API TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
+												TNC_ConnectionID connection_id,
+												TNC_ConnectionState new_state)
 {
 	imc_state_t *state;
 
@@ -142,8 +142,8 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
 /**
  * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
-								  TNC_ConnectionID connection_id)
+TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
+											  TNC_ConnectionID connection_id)
 {
 	if (!imc_attestation)
 	{
@@ -228,11 +228,11 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
 /**
  * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
-								  TNC_ConnectionID connection_id,
-								  TNC_BufferReference msg,
-								  TNC_UInt32 msg_len,
-								  TNC_MessageType msg_type)
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
+											  TNC_ConnectionID connection_id,
+											  TNC_BufferReference msg,
+											  TNC_UInt32 msg_len,
+											  TNC_MessageType msg_type)
 {
 	imc_state_t *state;
 	imc_msg_t *in_msg;
@@ -259,15 +259,15 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
 /**
  * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
  */
-TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
-									  TNC_ConnectionID connection_id,
-									  TNC_UInt32 msg_flags,
-									  TNC_BufferReference msg,
-									  TNC_UInt32 msg_len,
-									  TNC_VendorID msg_vid,
-									  TNC_MessageSubtype msg_subtype,
-									  TNC_UInt32 src_imv_id,
-									  TNC_UInt32 dst_imc_id)
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
+												  TNC_ConnectionID connection_id,
+												  TNC_UInt32 msg_flags,
+												  TNC_BufferReference msg,
+												  TNC_UInt32 msg_len,
+												  TNC_VendorID msg_vid,
+												  TNC_MessageSubtype msg_subtype,
+												  TNC_UInt32 src_imv_id,
+												  TNC_UInt32 dst_imc_id)
 {
 	imc_state_t *state;
 	imc_msg_t *in_msg;
@@ -294,8 +294,8 @@ TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
 /**
  * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
-							   TNC_ConnectionID connection_id)
+TNC_Result TNC_IMC_API TNC_IMC_BatchEnding(TNC_IMCID imc_id,
+										   TNC_ConnectionID connection_id)
 {
 	if (!imc_attestation)
 	{
@@ -308,7 +308,7 @@ TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
 /**
  * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
+TNC_Result TNC_IMC_API TNC_IMC_Terminate(TNC_IMCID imc_id)
 {
 	if (!imc_attestation)
 	{
@@ -327,7 +327,7 @@ TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
 /**
  * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
  */
-TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
+TNC_Result TNC_IMC_API TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
 								TNC_TNCC_BindFunctionPointer bind_function)
 {
 	if (!imc_attestation)
diff --git a/src/libpts/plugins/imc_swid/Makefile.am b/src/libpts/plugins/imc_swid/Makefile.am
index d73c6d1..ddf5964 100644
--- a/src/libpts/plugins/imc_swid/Makefile.am
+++ b/src/libpts/plugins/imc_swid/Makefile.am
@@ -25,7 +25,7 @@ AM_CPPFLAGS = \
 	-DSWID_DIRECTORY=\"${prefix}/share\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-swid.la
 
diff --git a/src/libpts/plugins/imc_swid/Makefile.in b/src/libpts/plugins/imc_swid/Makefile.in
index 5840263..6c3923a 100644
--- a/src/libpts/plugins/imc_swid/Makefile.in
+++ b/src/libpts/plugins/imc_swid/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -427,7 +431,7 @@ AM_CPPFLAGS = \
 	-DSWID_DIRECTORY=\"${prefix}/share\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imc-swid.la
 imc_swid_la_LIBADD = \
diff --git a/src/libpts/plugins/imc_swid/imc_swid.c b/src/libpts/plugins/imc_swid/imc_swid.c
index d4aaeff..ef3a6a3 100644
--- a/src/libpts/plugins/imc_swid/imc_swid.c
+++ b/src/libpts/plugins/imc_swid/imc_swid.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -24,12 +24,15 @@
 
 #include <imc/imc_agent.h>
 #include <imc/imc_msg.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_angel.h>
 
 #include <tncif_pa_subtypes.h>
 
 #include <pen/pen.h>
 #include <utils/debug.h>
 
+#define SWID_GENERATOR	"/usr/local/bin/swid_generator"
 
 /* IMC definitions */
 
@@ -128,12 +131,177 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
 	return TNC_RESULT_SUCCESS;
 }
 
-static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
+/**
+ * Add one or multiple SWID Inventory attributes to the send queue
+ */
+static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
+							   uint32_t request_id, bool full_tags,
+							   swid_inventory_t *targets)
 {
-	imc_msg_t *out_msg;
+	pa_tnc_attr_t *attr, *attr_angel, *attr_error;
 	imc_swid_state_t *swid_state;
+	swid_inventory_t *swid_inventory;
+	char *swid_directory, *swid_generator;
+	uint32_t eid_epoch;
+	size_t max_attr_size, attr_size, entry_size;
+	bool first = TRUE, swid_pretty, swid_full;
 	enumerator_t *enumerator;
+
+	swid_directory = lib->settings->get_str(lib->settings,
+								"%s.plugins.imc-swid.swid_directory",
+								 SWID_DIRECTORY, lib->ns);
+	swid_generator = lib->settings->get_str(lib->settings,
+								"%s.plugins.imc-swid.swid_generator",
+								 SWID_GENERATOR, lib->ns);
+	swid_pretty = lib->settings->get_bool(lib->settings,
+								"%s.plugins.imc-swid.swid_pretty",
+								 FALSE, lib->ns);
+	swid_full = lib->settings->get_bool(lib->settings,
+								"%s.plugins.imc-swid.swid_full",
+								 FALSE, lib->ns);
+
+	swid_inventory = swid_inventory_create(full_tags);
+	if (!swid_inventory->collect(swid_inventory, swid_directory, swid_generator,
+								 targets, swid_pretty, swid_full))
+	{
+		swid_inventory->destroy(swid_inventory);
+		attr_error = swid_error_create(TCG_SWID_ERROR, request_id,
+								 0, "error in SWID tag collection");
+		msg->add_attribute(msg, attr_error);
+		return FALSE;
+	}
+	DBG1(DBG_IMC, "collected %d SWID tag%s%s",
+		 swid_inventory->get_count(swid_inventory), full_tags ? "" : " ID",
+		 swid_inventory->get_count(swid_inventory) == 1 ? "" : "s");
+
+	swid_state = (imc_swid_state_t*)state;
+	eid_epoch = swid_state->get_eid_epoch(swid_state);
+
+	/**
+	 * Compute the maximum TCG SWID Tag [ID] Inventory attribute size
+	 * leaving space for an additional ITA Angel attribute
+	 */
+	max_attr_size = state->get_max_msg_len(state) -
+					PA_TNC_HEADER_SIZE - PA_TNC_ATTR_HEADER_SIZE;
+
+	if (full_tags)
+	{
+		tcg_swid_attr_tag_inv_t *swid_attr;
+		swid_tag_t *tag;
+		chunk_t encoding, tag_file_path;
+
+		/* At least one TCG Tag Inventory attribute is sent */
+		attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_INV_MIN_SIZE;
+		attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
+
+		enumerator = swid_inventory->create_enumerator(swid_inventory);
+		while (enumerator->enumerate(enumerator, &tag))
+		{
+			tag_file_path = tag->get_tag_file_path(tag);
+			encoding = tag->get_encoding(tag);
+			entry_size = 2 + tag_file_path.len + 4 + encoding.len;
+
+			/* Check for oversize tags that cannot be transported */
+			if (PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_INV_MIN_SIZE +
+				entry_size > max_attr_size)
+			{
+				attr_error = swid_error_create(TCG_SWID_RESPONSE_TOO_LARGE,
+											   request_id, max_attr_size,
+											   "oversize SWID tag omitted");
+				msg->add_attribute(msg, attr_error);
+				continue;
+			}
+
+			if (attr_size + entry_size > max_attr_size)
+			{
+				if (first)
+				{
+					/**
+					 * Send an ITA Start Angel attribute to the IMV signalling
+					 * that multiple TGC SWID Tag Inventory attributes follow
+					 */
+					attr_angel = ita_attr_angel_create(TRUE);
+					msg->add_attribute(msg, attr_angel);
+					first = FALSE;
+				}
+				msg->add_attribute(msg, attr);
+
+				/* create the next TCG SWID Tag Inventory attribute */
+				attr_size = PA_TNC_ATTR_HEADER_SIZE +
+							TCG_SWID_TAG_INV_MIN_SIZE;
+				attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
+			}
+			swid_attr = (tcg_swid_attr_tag_inv_t*)attr;
+			swid_attr->add(swid_attr, tag->get_ref(tag));
+			attr_size += entry_size;
+		}
+		enumerator->destroy(enumerator);
+	}
+	else
+	{
+		tcg_swid_attr_tag_id_inv_t *swid_id_attr;
+		swid_tag_id_t *tag_id;
+		chunk_t tag_creator, unique_sw_id, tag_file_path;
+
+		/* At least one TCG Tag ID Inventory attribute is sent */
+		attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_ID_INV_MIN_SIZE;
+		attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
+		swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
+
+		enumerator = swid_inventory->create_enumerator(swid_inventory);
+		while (enumerator->enumerate(enumerator, &tag_id))
+		{
+			tag_creator = tag_id->get_tag_creator(tag_id);
+			unique_sw_id = tag_id->get_unique_sw_id(tag_id, &tag_file_path);
+			entry_size = 2 + tag_creator.len + 2 + unique_sw_id.len +
+						 2 + tag_file_path.len;
+
+			if (attr_size + entry_size > max_attr_size)
+			{
+				if (first)
+				{
+					/**
+					 * Send an ITA Start Angel attribute to the IMV signalling
+					 * that multiple TGC SWID Tag ID Inventory attributes follow
+					 */
+					attr_angel = ita_attr_angel_create(TRUE);
+					msg->add_attribute(msg, attr_angel);
+					first = FALSE;
+				}
+				msg->add_attribute(msg, attr);
+
+				/* create the next TCG SWID Tag ID Inventory attribute */
+				attr_size = PA_TNC_ATTR_HEADER_SIZE +
+							TCG_SWID_TAG_ID_INV_MIN_SIZE;
+				attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
+			}
+			swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
+			swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id));
+			attr_size += entry_size;
+		}
+		enumerator->destroy(enumerator);
+	}
+	msg->add_attribute(msg, attr);
+	swid_inventory->destroy(swid_inventory);
+
+	if (!first)
+	{
+		/**
+		 * If we sent an ITA Start Angel attribute in the first place,
+		 * terminate by appending a matching ITA Stop Angel attribute.
+		 */
+		attr_angel = ita_attr_angel_create(FALSE);
+		msg->add_attribute(msg, attr_angel);
+	}
+
+	return TRUE;
+}
+
+static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
+{
+	imc_msg_t *out_msg;
 	pa_tnc_attr_t *attr;
+	enumerator_t *enumerator;
 	pen_type_t type;
 	TNC_Result result;
 	bool fatal_error = FALSE;
@@ -145,18 +313,16 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
 		return result;
 	}
 	out_msg = imc_msg_create_as_reply(in_msg);
-	swid_state = (imc_swid_state_t*)state;
 
 	/* analyze PA-TNC attributes */
 	enumerator = in_msg->create_attribute_enumerator(in_msg);
 	while (enumerator->enumerate(enumerator, &attr))
 	{
 		tcg_swid_attr_req_t *attr_req;
-		u_int8_t flags;
-		u_int32_t request_id, eid_epoch;
-		swid_inventory_t *swid_inventory, *targets;
-		char *swid_directory;
+		uint8_t flags;
+		uint32_t request_id;
 		bool full_tags;
+		swid_inventory_t *targets;
 
 		type = attr->get_type(attr);
 
@@ -169,7 +335,6 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
 		flags = attr_req->get_flags(attr_req);
 		request_id = attr_req->get_request_id(attr_req);
 		targets = attr_req->get_targets(attr_req);
-		eid_epoch = swid_state->get_eid_epoch(swid_state);
 
 		if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C))
 		{
@@ -180,33 +345,10 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
 		}
 		full_tags = (flags & TCG_SWID_ATTR_REQ_FLAG_R) == 0;
 
-		swid_directory = lib->settings->get_str(lib->settings,
-								"%s.plugins.imc-swid.swid_directory",
-								 SWID_DIRECTORY, lib->ns);
-		swid_inventory = swid_inventory_create(full_tags);
-		if (!swid_inventory->collect(swid_inventory, swid_directory, targets))
+		if (!add_swid_inventory(state, out_msg, request_id, full_tags, targets))
 		{
-			swid_inventory->destroy(swid_inventory);
-			attr = swid_error_create(TCG_SWID_ERROR, request_id,
-									 0, "error in SWID tag collection");
-			out_msg->add_attribute(out_msg, attr);
 			break;
 		}
-		DBG1(DBG_IMC, "collected %d SWID tag%s%s",
-			 swid_inventory->get_count(swid_inventory), full_tags ? "" : " ID",
-			 swid_inventory->get_count(swid_inventory) == 1 ? "" : "s");
-
-		if (full_tags)
-		{
-			attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1,
-												swid_inventory);
-		}
-		else
-		{
-			attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1,
-												swid_inventory);
-		}
-		out_msg->add_attribute(out_msg, attr);
 	}
 	enumerator->destroy(enumerator);
 
diff --git a/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in b/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
index 6945d87..8b7b50f 100644
--- a/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
+++ b/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
@@ -1,30 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
-<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
-  <entitlement_required_indicator>true</entitlement_required_indicator>
-  <product_title>strongSwan</product_title>
-  <product_version>
-    <name>@VERSION_MAJOR at .@VERSION_MINOR at .@VERSION_BUILD@@VERSION_REVIEW@</name>
-    <numeric>
-      <major>@VERSION_MAJOR@</major>
-      <minor>@VERSION_MINOR@</minor>
-      <build>@VERSION_BUILD@</build>
-      <review>@VERSION_REVIEW@</review>
-    </numeric>
-  </product_version>
-  <software_creator>
-    <name>strongSwan Project</name>
-    <regid>regid.2004-03.org.strongswan</regid>
-  </software_creator>
-  <software_licensor>
-    <name>strongSwan Project</name>
-    <regid>regid.2004-03.org.strongswan</regid>
-  </software_licensor>
-  <software_id>
-    <unique_id>strongSwan- at VERSION_MAJOR@- at VERSION_MINOR@- at VERSION_BUILD@@VERSION_REVIEW@</unique_id>
-    <tag_creator_regid>regid.2004-03.org.strongswan</tag_creator_regid>
-  </software_id>
-  <tag_creator>
-    <name>strongSwan Project</name>
-    <regid>regid.2004-03.org.strongswan</regid>
-  </tag_creator>
-</software_identification_tag>
+
+<SoftwareIdentity
+  name="strongSwan"
+  uniqueId="strongSwan- at VERSION_MAJOR@- at VERSION_MINOR@- at VERSION_BUILD@@VERSION_REVIEW@"
+  version="@VERSION_MAJOR at .@VERSION_MINOR at .@VERSION_BUILD@@VERSION_REVIEW@" versionScheme="alphanumeric"
+  xmlns="http://standards.iso.org/iso/19770/-2/2014/schema.xsd">
+  <Entity
+    name="strongSwan Project"
+    regid="regid.2004-03.org.strongswan"
+    role="publisher licensor tagcreator"/>
+</SoftwareIdentity>
diff --git a/src/libpts/plugins/imv_attestation/Makefile.am b/src/libpts/plugins/imv_attestation/Makefile.am
index 8d18f14..8dc74fd 100644
--- a/src/libpts/plugins/imv_attestation/Makefile.am
+++ b/src/libpts/plugins/imv_attestation/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 	-DPLUGINS=\""${attest_plugins}\""
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-attestation.la
 
diff --git a/src/libpts/plugins/imv_attestation/Makefile.in b/src/libpts/plugins/imv_attestation/Makefile.in
index ff94363..b0e3787 100644
--- a/src/libpts/plugins/imv_attestation/Makefile.in
+++ b/src/libpts/plugins/imv_attestation/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -275,6 +275,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -293,6 +294,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -320,6 +322,7 @@ 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@
@@ -411,6 +414,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -429,7 +433,7 @@ AM_CPPFLAGS = \
 	-DPLUGINS=\""${attest_plugins}\""
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-attestation.la
 imv_attestation_la_LIBADD = \
diff --git a/src/libpts/plugins/imv_attestation/attest.c b/src/libpts/plugins/imv_attestation/attest.c
index 8f4df39..63c0023 100644
--- a/src/libpts/plugins/imv_attestation/attest.c
+++ b/src/libpts/plugins/imv_attestation/attest.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -19,8 +19,10 @@
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
-#include <syslog.h>
 #include <libgen.h>
+#ifdef HAVE_SYSLOG
+# include <syslog.h>
+#endif
 
 #include <library.h>
 #include <utils/debug.h>
@@ -43,9 +45,6 @@ static bool stderr_quiet = TRUE;
  */
 static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
 {
-	int priority = LOG_INFO;
-	char buffer[8192];
-	char *current = buffer, *next;
 	va_list args;
 
 	if (level <= debug_level)
@@ -58,22 +57,30 @@ static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
 			va_end(args);
 		}
 
-		/* write in memory buffer first */
-		va_start(args, fmt);
-		vsnprintf(buffer, sizeof(buffer), fmt, args);
-		va_end(args);
-
-		/* do a syslog with every line */
-		while (current)
+#ifdef HAVE_SYSLOG
 		{
-			next = strchr(current, '\n');
-			if (next)
+			int priority = LOG_INFO;
+			char buffer[8192];
+			char *current = buffer, *next;
+
+			/* write in memory buffer first */
+			va_start(args, fmt);
+			vsnprintf(buffer, sizeof(buffer), fmt, args);
+			va_end(args);
+
+			/* do a syslog with every line */
+			while (current)
 			{
-				*(next++) = '\0';
+				next = strchr(current, '\n');
+				if (next)
+				{
+					*(next++) = '\0';
+				}
+				syslog(priority, "%s\n", current);
+				current = next;
 			}
-			syslog(priority, "%s\n", current);
-			current = next;
 		}
+#endif /* HAVE_SYSLOG */
 	}
 }
 
@@ -91,7 +98,9 @@ static void cleanup(void)
 	attest->destroy(attest);
 	libpts_deinit();
 	libimcv_deinit();
+#ifdef HAVE_SYSLOG
 	closelog();
+#endif
 }
 
 static void do_args(int argc, char *argv[])
@@ -144,9 +153,9 @@ static void do_args(int argc, char *argv[])
 			{ "directory", required_argument, NULL, 'D' },
 			{ "dir", required_argument, NULL, 'D' },
 			{ "file", required_argument, NULL, 'F' },
-			{ "sha1-ima", no_argument, NULL, 'I' },
 			{ "package", required_argument, NULL, 'G' },
 			{ "key", required_argument, NULL, 'K' },
+			{ "measdir", required_argument, NULL, 'M' },
 			{ "owner", required_argument, NULL, 'O' },
 			{ "product", required_argument, NULL, 'P' },
 			{ "relative", no_argument, NULL, 'R' },
@@ -294,9 +303,6 @@ static void do_args(int argc, char *argv[])
 					exit(EXIT_FAILURE);
 				}
 				continue;
-			case 'I':
-				attest->set_algo(attest, PTS_MEAS_ALGO_SHA1_IMA);
-				continue;
 			case 'K':
 			{
 				chunk_t aik;
@@ -308,6 +314,12 @@ static void do_args(int argc, char *argv[])
 				}
 				continue;
 			}
+			case 'M':
+				if (!attest->set_meas_directory(attest, optarg))
+				{
+					exit(EXIT_FAILURE);
+				}
+				continue;
 			case 'O':
 				attest->set_owner(attest, optarg);
 				continue;
@@ -437,7 +449,9 @@ int main(int argc, char *argv[])
 
 	/* enable attest debugging hook */
 	dbg = attest_dbg;
+#ifdef HAVE_SYSLOG
 	openlog("attest", 0, LOG_DEBUG);
+#endif
 
 	atexit(library_deinit);
 
@@ -471,4 +485,3 @@ int main(int argc, char *argv[])
 
 	exit(EXIT_SUCCESS);
 }
-
diff --git a/src/libpts/plugins/imv_attestation/attest_db.c b/src/libpts/plugins/imv_attestation/attest_db.c
index 7a8a113..d7f45ad 100644
--- a/src/libpts/plugins/imv_attestation/attest_db.c
+++ b/src/libpts/plugins/imv_attestation/attest_db.c
@@ -79,6 +79,11 @@ struct private_attest_db_t {
 	int fid;
 
 	/**
+	 * Directory where file measurement are to be taken
+	 */
+	char *meas_dir;
+
+	/**
 	 *  AIK to be queried
 	 */
 	chunk_t key;
@@ -193,6 +198,21 @@ char* print_cfn(pts_comp_func_name_t *cfn)
 	return buf;
 }
 
+/**
+ * Get the directory separator to append to a path
+ */
+static const char* get_separator(const char *path)
+{
+	if (streq(path, DIRECTORY_SEPARATOR))
+	{	/* root directory on Unix file system, no separator */
+		return "";
+	}
+	else
+	{	/* non-root or Windows path, use system specific separator */
+		return DIRECTORY_SEPARATOR;
+	}
+}
+
 METHOD(attest_db_t, set_component, bool,
 	private_attest_db_t *this, char *comp, bool create)
 {
@@ -309,9 +329,9 @@ METHOD(attest_db_t, set_directory, bool,
 		return FALSE;
 	}
 
-	/* remove trailing '/' character if not root directory */
+	/* remove trailing '/' or '\' character if not root directory */
 	len = strlen(dir);
-	if (len > 1 && dir[len-1] == '/')
+	if (len > 1 && dir[len-1] == DIRECTORY_SEPARATOR[0])
 	{
 		dir[len-1] = '\0';
 	}
@@ -385,7 +405,6 @@ METHOD(attest_db_t, set_file, bool,
 	private_attest_db_t *this, char *file, bool create)
 {
 	int fid;
-	char *sep;
 	enumerator_t *e;
 
 	if (this->file)
@@ -399,7 +418,6 @@ METHOD(attest_db_t, set_file, bool,
 	{
 		return TRUE;
 	}
-	sep = streq(this->dir, "/") ? "" : "/";
 	e = this->db->query(this->db, "SELECT id FROM files "
 						"WHERE dir = ? AND name = ?",
 						DB_INT, this->did, DB_TEXT, file, DB_INT);
@@ -418,7 +436,8 @@ METHOD(attest_db_t, set_file, bool,
 
 	if (!create)
 	{
-		printf("file '%s%s%s' not found in database\n", this->dir, sep, file);
+		printf("file '%s%s%s' not found in database\n",
+			   this->dir, get_separator(this->dir), file);
 		return FALSE;
 	}
 
@@ -429,8 +448,8 @@ METHOD(attest_db_t, set_file, bool,
 	{
 		this->fid = fid;
 	}
-	printf("file '%s%s%s' %sinserted into database\n", this->dir, sep, file,
-		   this->fid ? "" : "could not be ");
+	printf("file '%s%s%s' %sinserted into database\n", this->dir,
+		   get_separator(this->dir), file, this->fid ? "" : "could not be ");
 
 	return this->fid > 0;
 }
@@ -470,6 +489,22 @@ METHOD(attest_db_t, set_fid, bool,
 	return this->fid > 0;
 }
 
+METHOD(attest_db_t, set_meas_directory, bool,
+	private_attest_db_t *this, char *dir)
+{
+	size_t len;
+
+	/* remove trailing '/' character if not root directory */
+	len = strlen(dir);
+	if (len > 1 && dir[len-1] == '/')
+	{
+		dir[len-1] = '\0';
+	}
+	this->meas_dir = strdup(dir);
+
+	return TRUE;
+}
+
 METHOD(attest_db_t, set_key, bool,
 	private_attest_db_t *this, chunk_t key, bool create)
 {
@@ -1297,7 +1332,7 @@ METHOD(attest_db_t, list_hashes, void,
 			printf("%d %N value%s found for file '%s%s%s'\n", count,
 				   pts_meas_algorithm_names, this->algo,
 				   (count == 1) ? "" : "s", this->dir,
-				   streq(this->dir, "/") ? "" : "/", this->file);
+				   get_separator(this->dir), this->file);
 		}
 	}
 	else if (this->file)
@@ -1568,12 +1603,13 @@ METHOD(attest_db_t, list_sessions, void,
  */
 static bool insert_file_hash(private_attest_db_t *this,
 							 pts_meas_algorithms_t algo,
-							 chunk_t measurement, int fid, bool ima,
+							 chunk_t measurement, int fid,
 							 int *hashes_added, int *hashes_updated)
 {
 	enumerator_t *e;
 	chunk_t hash;
 	char *label;
+	bool insert = TRUE, update = FALSE;
 
 	label = "could not be created";
 
@@ -1581,46 +1617,50 @@ static bool insert_file_hash(private_attest_db_t *this,
 		"SELECT hash FROM file_hashes WHERE algo = ? "
 		"AND file = ? AND product = ? AND device = 0",
 		DB_INT, algo, DB_UINT, fid, DB_UINT, this->pid, DB_BLOB);
+
 	if (!e)
 	{
 		printf("file_hashes query failed\n");
 		return FALSE;
 	}
-	if (e->enumerate(e, &hash))
+
+	while (e->enumerate(e, &hash))
 	{
+		update = TRUE;
+
 		if (chunk_equals(measurement, hash))
 		{
 			label = "exists and equals";
-		}
-		else
-		{
-			if (this->db->execute(this->db, NULL,
-				"UPDATE file_hashes SET hash = ? WHERE algo = ? "
-				"AND file = ? AND product = ? and device = 0",
-				DB_BLOB, measurement, DB_INT, algo, DB_UINT, fid,
-				DB_UINT, this->pid) == 1)
-			{
-				label = "updated";
-				(*hashes_updated)++;
-			}
+			insert = FALSE;
+			break;
 		}
 	}
-	else
+	e->destroy(e);
+
+	if (insert)
 	{
 		if (this->db->execute(this->db, NULL,
 			"INSERT INTO file_hashes "
 			"(file, product, device, algo, hash) "
 			"VALUES (?, ?, 0, ?, ?)",
 			DB_UINT, fid, DB_UINT, this->pid,
-			DB_INT, algo, DB_BLOB, measurement) == 1)
+			DB_INT, algo, DB_BLOB, measurement) != 1)
+		{
+			printf("file_hash insertion failed\n");
+			return FALSE;
+		}
+		if (update)
+		{
+			label = "updated";
+			(*hashes_updated)++;
+		}
+		else
 		{
 			label = "created";
 			(*hashes_added)++;
 		}
 	}
-	e->destroy(e);
-
-	printf("     %#B - %s%s\n", &measurement, ima ? "ima - " : "", label);
+	printf("     %#B - %s\n", &measurement, label);
 	return TRUE;
 }
 
@@ -1629,33 +1669,24 @@ static bool insert_file_hash(private_attest_db_t *this,
  */
 static bool add_hash(private_attest_db_t *this)
 {
-	char *pathname, *filename, *sep, *label, *pos;
-	char ima_buffer[IMA_MAX_NAME_LEN + 1];
-	chunk_t measurement, ima_template;
+	char *pathname, *filename, *label;
+	const char *sep;
 	pts_file_meas_t *measurements;
+	chunk_t measurement;
 	hasher_t *hasher = NULL;
-	bool ima = FALSE;
 	int fid, files_added = 0, hashes_added = 0, hashes_updated = 0;
-	int len, ima_hashes_added = 0, ima_hashes_updated = 0;
 	enumerator_t *enumerator, *e;
 
-	if (this->algo == PTS_MEAS_ALGO_SHA1_IMA)
+	if (!this->meas_dir)
 	{
-		ima = TRUE;
-		this->algo = PTS_MEAS_ALGO_SHA1;
-		hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
-		if (!hasher)
-		{
-			printf("could not create hasher\n");
-			return FALSE;
-		}
+		this->meas_dir = strdup(this->dir);
 	}
-	sep = streq(this->dir, "/") ? "" : "/";
+	sep = get_separator(this->meas_dir);
 
 	if (this->fid)
 	{
 		/* build pathname from directory path and relative filename */
-		if (asprintf(&pathname, "%s%s%s", this->dir, sep, this->file) == -1)
+		if (asprintf(&pathname, "%s%s%s", this->meas_dir, sep, this->file) == -1)
 		{
 			return FALSE;
 		}
@@ -1665,7 +1696,7 @@ static bool add_hash(private_attest_db_t *this)
 	}
 	else
 	{
-		measurements = pts_file_meas_create_from_path(0, this->dir, TRUE,
+		measurements = pts_file_meas_create_from_path(0, this->meas_dir, TRUE,
 													  TRUE, this->algo);
 	}
 	if (!measurements)
@@ -1717,59 +1748,18 @@ static bool add_hash(private_attest_db_t *this)
 		printf("%4d: %s - %s\n", fid, filename, label);
 
 		/* compute file measurement hash */
-		if (!insert_file_hash(this, this->algo, measurement, fid, FALSE,
+		if (!insert_file_hash(this, this->algo, measurement, fid,
 							  &hashes_added, &hashes_updated))
 		{
 			break;
 		}
-		if (!ima)
-		{
-			continue;
-		}
-
-		/* compute IMA template hash */
-		pos = ima_buffer;
-		len = IMA_MAX_NAME_LEN;
-		if (!this->relative)
-		{
-			strncpy(pos, this->dir, len);
-			len = max(0, len - strlen(this->dir));
-			pos = ima_buffer + IMA_MAX_NAME_LEN - len;
-			strncpy(pos, sep, len);
-			len = max(0, len - strlen(sep));
-			pos = ima_buffer + IMA_MAX_NAME_LEN - len;
-		}
-		strncpy(pos, filename, len);
-		ima_buffer[IMA_MAX_NAME_LEN] = '\0';
-		ima_template = chunk_create(ima_buffer, sizeof(ima_buffer));
-		if (!hasher->get_hash(hasher, measurement, NULL) ||
-			!hasher->get_hash(hasher, ima_template, measurement.ptr))
-		{
-			printf("could not compute IMA template hash\n");
-			break;
-		}
-		if (!insert_file_hash(this, PTS_MEAS_ALGO_SHA1_IMA, measurement, fid,
-							  TRUE, &ima_hashes_added, &ima_hashes_updated))
-		{
-			break;
-		}
 	}
 	enumerator->destroy(enumerator);
 
-	printf("%d measurements, added %d new files, %d file hashes",
-		    measurements->get_file_count(measurements), files_added,
-			hashes_added);
-	if (ima)
-	{
-		printf(", %d ima hashes", ima_hashes_added);
-		hasher->destroy(hasher);
-	}
-	printf(", updated %d file hashes", hashes_updated);
-	if (ima)
-	{
-		printf(", %d ima hashes", ima_hashes_updated);
-	}
-	printf("\n");
+	printf("%d measurements, added %d new files, %d file hashes, "
+		   "updated %d file hashes\n",
+			measurements->get_file_count(measurements),
+		    files_added, hashes_added, hashes_updated);
 	measurements->destroy(measurements);
 
 	return TRUE;
@@ -1780,22 +1770,6 @@ METHOD(attest_db_t, add, bool,
 {
 	bool success = FALSE;
 
-	/* add key/component pair */
-	if (this->kid && this->cid)
-	{
-		success = this->db->execute(this->db, NULL,
-					"INSERT INTO key_component (key, component, seq_no) "
-					"VALUES (?, ?, ?)",
-					DB_UINT, this->kid, DB_UINT, this->cid,
-					DB_UINT, this->seq_no) == 1;
-
-		printf("key/component pair (%d/%d) %sinserted into database at "
-			   "position %d\n", this->kid, this->cid,
-			    success ? "" : "could not be ", this->seq_no);
-
-		return success;
-	}
-
 	/* add directory or file hash measurement for a given product */
 	if (this->did && this->pid)
 	{
@@ -1844,8 +1818,8 @@ METHOD(attest_db_t, delete, bool,
 								DB_UINT, this->algo, DB_UINT, this->pid,
 								DB_UINT, this->fid) > 0;
 
-		printf("%4d: %s%s%s\n", this->fid, this->dir,
-				streq(this->dir, "/") ? "" : "/", this->file);
+		printf("%4d: %s%s%s\n", this->fid, this->dir, get_separator(this->dir),
+				this->file);
 		printf("%N value for product '%s' %sdeleted from database\n",
 				pts_meas_algorithm_names, this->algo, this->product,
 				success ? "" : "could not be ");
@@ -1869,19 +1843,6 @@ METHOD(attest_db_t, delete, bool,
 		return success;
 	}
 
-	/* delete key/component pair */
-	if (this->kid && this->cid)
-	{
-		success = this->db->execute(this->db, NULL,
-								"DELETE FROM key_component "
-								"WHERE key = ? AND component = ?",
-								DB_UINT, this->kid, DB_UINT, this->cid) > 0;
-
-		printf("key/component pair (%d/%d) %sdeleted from database\n",
-				this->kid, this->cid, success ? "" : "could not be ");
-		return success;
-	}
-
 	if (this->cid)
 	{
 		success = this->db->execute(this->db, NULL,
@@ -1900,7 +1861,7 @@ METHOD(attest_db_t, delete, bool,
 								DB_UINT, this->fid) > 0;
 
 		printf("file '%s%s%s' %sdeleted from database\n", this->dir,
-			   streq(this->dir, "/") ? "" : "/", this->file,
+			   get_separator(this->dir), this->file,
 			   success ? "" : "could not be ");
 		return success;
 	}
@@ -1970,6 +1931,7 @@ METHOD(attest_db_t, destroy, void,
 	free(this->version);
 	free(this->file);
 	free(this->dir);
+	free(this->meas_dir);
 	free(this->owner);
 	free(this->key.ptr);
 	free(this);
@@ -1990,6 +1952,7 @@ attest_db_t *attest_db_create(char *uri)
 			.set_did = _set_did,
 			.set_file = _set_file,
 			.set_fid = _set_fid,
+			.set_meas_directory = _set_meas_directory,
 			.set_key = _set_key,
 			.set_kid = _set_kid,
 			.set_package = _set_package,
diff --git a/src/libpts/plugins/imv_attestation/attest_db.h b/src/libpts/plugins/imv_attestation/attest_db.h
index d0a48d8..07e55cc 100644
--- a/src/libpts/plugins/imv_attestation/attest_db.h
+++ b/src/libpts/plugins/imv_attestation/attest_db.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -84,6 +84,14 @@ struct attest_db_t {
 	bool (*set_fid)(attest_db_t *this, int fid);
 
 	/**
+	 * Set path to directory where file[s] are to be measured
+	 *
+	 * @param meas_dir		measurement directory
+	 * @return				TRUE if successful
+	 */
+	bool (*set_meas_directory)(attest_db_t *this, char *dir);
+
+	/**
 	 * Set functional component to be queried
 	 *
 	 * @param key			AIK
diff --git a/src/libpts/plugins/imv_attestation/build-database.sh b/src/libpts/plugins/imv_attestation/build-database.sh
index be1024d..f16b5d1 100755
--- a/src/libpts/plugins/imv_attestation/build-database.sh
+++ b/src/libpts/plugins/imv_attestation/build-database.sh
@@ -1,221 +1,84 @@
 #!/bin/sh
 
-p="Ubuntu 12.04 i686"
+p="Ubuntu 14.04 x86_64"
+a="x86_64-linux-gnu"
+k="3.13.0-30-generic"
 
-ipsec attest --add --product "$p" --sha1-ima --dir  /sbin 
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/sbin
-ipsec attest --add --product "$p" --sha1-ima --dir  /bin
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/bin
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/acpi
-ipsec attest --add --product "$p" --sha1-ima --file /etc/init.d/rc
-ipsec attest --add --product "$p" --sha1-ima --file /etc/init.d/rcS
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/network/if-post-down.d
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/network/if-pre-up.d
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/network/if-up.d
-ipsec attest --add --product "$p" --sha1-ima --file /etc/NetworkManager/dispatcher.d/01ifupdown
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/ppp/ip-down.d
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/rc2.d
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/rcS.d
-ipsec attest --add --product "$p" --sha1-ima --file /etc/rc.local
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/resolvconf/update.d
-ipsec attest --add --product "$p" --sha1-ima --file /etc/resolvconf/update-libc.d/avahi-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir  /etc/update-motd.d
-ipsec attest --add --product "$p" --sha1-ima --file /lib/crda/setregdomain
-ipsec attest --add --product "$p" --sha1-ima --file /lib/init/apparmor-profile-load
-ipsec attest --add --product "$p" --sha1-ima --file /lib/resolvconf/list-records
-ipsec attest --add --product "$p" --sha1-ima --dir  /lib/udev
-ipsec attest --add --product "$p" --sha1-ima --file /lib/ufw/ufw-init
-ipsec attest --add --product "$p" --sha1-ima --file /opt/Adobe/Reader9/Reader/intellinux/bin/acroread
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/accountsservice/accounts-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/apt/methods
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/at-spi2-core
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/avahi/avahi-daemon-check-dns.sh
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/bamf/bamfdaemon
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/ConsoleKit
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/ConsoleKit/run-seat.d
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/ConsoleKit/run-session.d
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/cups/notifier
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/dconf/dconf-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/deja-dup/deja-dup/deja-dup-monitor
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/evolution/3.2/evolution-alarm-notify
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/firefox/firefox
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/firefox/plugin-container
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gcc/i686-linux-gnu/4.6/cc1
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gcc/i686-linux-gnu/4.6/collect2
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/geoclue/geoclue-master
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/git-core
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-desktop3/check_gl_texture_size
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-disk-utility/gdu-notification-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-online-accounts/goa-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/gnome-settings-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-user-share/gnome-user-share
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-screensaver/gnome-screensaver-dialog
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/gvfs
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gvfs//gvfs-fuse-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/i386-linux-gnu/colord/colord
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/i386-linux-gnu/gconf
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-application/indicator-application-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-appmenu/hud-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-datetime/indicator-datetime-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-messages/indicator-messages-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-printers/indicator-printers-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-session/indicator-session-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-sound/indicator-sound-service
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/lightdm
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/NetworkManager/nm-dhcp-client.action
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/NetworkManager/nm-dispatcher.action
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/notify-osd/notify-osd
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/nux/unity_support_test
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/pm-utils/power.d
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/pm-utils/sleep.d
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/policykit-1/polkitd
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/pulseaudio/pulse/gconf-helper
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/rtkit/rtkit-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/system-service/system-service-d
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/telepathy/mission-control-5
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/thunderbird/thunderbird
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/ubuntuone-client
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/ubuntu-geoip/ubuntu-geoip-provider
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/ubuntu-sso-client
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/udisks
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity/unity-panel-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-applications/unity-applications-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-files/unity-files-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/unity-lens-music
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-video/unity-lens-video
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-scope-video-remote/unity-scope-video-remote
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/update-manager/release-upgrade-motd
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/lib/update-notifier
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/upower/upowerd
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/libvte-2.90-9/gnome-pty-helper
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/zeitgeist/zeitgeist-fts
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport-checkreports
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport-gtk
-ipsec attest --add --product "$p" --sha1-ima --dir  /usr/share/language-tools
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/virtualbox/VBoxCreateUSBNode.sh
-ipsec attest --add --product "$p" --sha1-ima --relative --file /etc/ld.so.cache
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /lib/i386-linux-gnu
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /lib/i386-linux-gnu/security
-for file in `find /lib/modules/3.2.21ima/kernel -name *.ko`
+for hash in sha1 sha256
 do
-ipsec attest --add --product "$p" --sha1-ima --relative --file $file
-done
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /lib/plymouth
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /lib/plymouth/renderers
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /lib/security
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /opt/Adobe/Reader9/Reader/intellinux/lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/apache2/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/compiz
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/compizconfig/backends/
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/enchant
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libemiscwidgets.so.0.0.0
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libeutil.so.0.0.0
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libgnomecanvas.so.0.0.0
-for file in /usr/lib/firefox/*.so
-do
-ipsec attest --add --product "$p" --sha1-ima --relative --file $file
-done
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libbrowsercomps.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libdbusservice.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libmozgnome.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox-addons/extensions/globalmenu at ubuntu.com/components/libglobalmenu.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox-addons/plugins/nppdf.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/flashplugin-installer/libflashplayer.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/gedit/plugins
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/gnome-bluetooth
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/gnome-settings-daemon-3.0
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/gtk-2.0/2.10.0/menuproxies
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/gtk-3.0/3.0.0/menuproxies
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/gtk-3.0/3.0.0/theming-engines
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/alsa-lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/dri
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gconf/2
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gconv
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gio/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gtk-2.0/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gtk-2.0/2.10.0/engines
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gtk-2.0/2.10.0/immodules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gtk-3.0/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/immodules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/gvfs
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/libcanberra-0.28
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/mesa
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/mit-krb5
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/openssl-1.0.0/engines
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/pango/1.6.0/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/pkcs11
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/polkit-1/extensions
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/nss
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/sane
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/i386-linux-gnu/sse2
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/indicators3/7
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/indicator-messages/status-providers/1
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/libpeas-1.0/loaders
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/man-db/libman-2.6.1.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/man-db/libmandb-2.6.1.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/mission-control-plugins.0
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/ModemManager
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/nautilus/extensions-3.0
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/NetworkManager/libnm-settings-plugin-ifupdown.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/perl/5.14.2/auto/File/Glob/Glob.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/pulse-1.1/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/python2.7/lib-dynload
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/apt_inst.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/apt_pkg.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/cairo/_cairo.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/dbus/mainloop/qt.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/_dbus_bindings.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/_dbus_glib_bindings.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/duplicity/_librsync.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_gi.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_gobject/_gobject.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_glib/_glib.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/glib/_glib.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gobject/_gobject.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/atk.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gtk/_gtk.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gio/_gio.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gio/unix.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pango.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pangocairo.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pynotify/_pynotify.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/crypto.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/rand.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/SSL.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/simplejson/_speedups.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/sip.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/twisted/internet/_sigchld.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/twisted/python/_initgroups.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/xapian/_xapian.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/zope/interface/_zope_interface_coptimizations.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/rsyslog
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/sane
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/sse2
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/sudo
-for file in /usr/lib/thunderbird/*.so
-do
-ipsec attest --add --product "$p" --sha1-ima --relative --file $file
+  ipsec attest --add --product "$p" --$hash --dir  /sbin
+  ipsec attest --add --product "$p" --$hash --dir  /usr/sbin
+  ipsec attest --add --product "$p" --$hash --dir  /bin
+  ipsec attest --add --product "$p" --$hash --dir  /usr/bin
+
+  ipsec attest --add --product "$p" --$hash --file /etc/init.d/rc
+  ipsec attest --add --product "$p" --$hash --file /etc/init.d/rcS
+  ipsec attest --add --product "$p" --$hash --dir  /etc/network/if-pre-up.d
+  ipsec attest --add --product "$p" --$hash --dir  /etc/network/if-up.d
+  ipsec attest --add --product "$p" --$hash --dir  /etc/ppp/ip-down.d
+  ipsec attest --add --product "$p" --$hash --dir  /etc/rcS.d
+  ipsec attest --add --product "$p" --$hash --dir  /etc/rc2.d
+  ipsec attest --add --product "$p" --$hash --file /etc/rc.local
+  ipsec attest --add --product "$p" --$hash --dir  /etc/resolvconf/update.d
+  ipsec attest --add --product "$p" --$hash --file /etc/resolvconf/update-libc.d/avahi-daemon
+  ipsec attest --add --product "$p" --$hash --dir  /etc/update-motd.d
+
+  ipsec attest --add --product "$p" --$hash --dir  /lib
+  ipsec attest --add --product "$p" --$hash --file /lib/crda/setregdomain
+  ipsec attest --add --product "$p" --$hash --dir  /lib/ebtables
+  ipsec attest --add --product "$p" --$hash --file /lib/init/apparmor-profile-load
+  ipsec attest --add --product "$p" --$hash --file /lib/resolvconf/list-records
+  ipsec attest --add --product "$p" --$hash --dir  /lib/ufw
+  ipsec attest --add --product "$p" --$hash --dir  /lib/udev
+  ipsec attest --add --product "$p" --$hash --dir  /lib/systemd
+  ipsec attest --add --product "$p" --$hash --dir  /lib/xtables
+  ipsec attest --add --product "$p" --$hash --dir  /lib/$a
+  ipsec attest --add --product "$p" --$hash --dir  /lib/$a/plymouth
+  ipsec attest --add --product "$p" --$hash --dir  /lib/$a/plymouth/renderers
+  ipsec attest --add --product "$p" --$hash --dir  /lib/$a/security
+
+  ipsec attest --add --product "$p" --$hash --file /lib64/ld-linux-x86-64.so.2
+
+  for file in `find /usr/lib -name *.so`
+  do
+    ipsec attest --add --product "$p" --$hash --file $file
+  done
+
+  for file in `find /usr/lib -name *service`
+  do
+    ipsec attest --add --product "$p" --$hash --file $file
+  done
+
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/accountsservice
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/at-spi2-core
+  ipsec attest --add --product "$p" --$hash --file /usr/lib/avahi/avahi-daemon-check-dns.sh
+  ipsec attest --add --product "$p" --$hash --file /usr/lib/dbus-1.0/dbus-daemon-launch-helper
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/gvfs
+  ipsec attest --add --product "$p" --$hash --file /usr/lib/firefox/firefox
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/NetworkManager
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/pm-utils/power.d
+  ipsec attest --add --product "$p" --$hash --file /usr/lib/policykit-1/polkitd
+  ipsec attest --add --product "$p" --$hash --file /usr/lib/thunderbird/thunderbird
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/ubuntu-release-upgrader
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/update-notifier
+
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/$a
+  ipsec attest --add --product "$p" --$hash --file /usr/lib/$a/mesa/libGL.so.1.2.0
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/$a/samba
+  ipsec attest --add --product "$p" --$hash --dir  /usr/lib/$a/sasl2
+
+  ipsec attest --add --product "$p" --$hash --dir  /usr/share/language-tools
+
+  ipsec attest --add --product "$p" --$hash --file /init \
+                     --measdir /usr/share/initramfs-tools
+
+  ipsec attest --add --product "$p" --$hash --file /scripts/functions \
+                     --measdir /usr/share/initramfs-tools/scripts
+
+  for file in `find /lib/modules/$k -name *.ko`
+  do
+    ipsec attest --add --product "$p" --$hash --file $file
+  done
 done
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird/components/libdbusservice.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird/components/libmozgnome.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird-addons/extensions/globalmenu at ubuntu.com/components/libglobalmenu.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/xorg/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/xorg/modules/drivers
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/xorg/modules/extensions
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/lib/xorg/modules/input
-ipsec attest --add --product "$p" --sha1-ima --relative --dir  /usr/share/fonts/truetype/ubuntu-font-family
-ipsec attest --del --product "$p" --sha1                --file /lib/resolvconf/list-records
-ipsec attest --del --product "$p" --sha1-ima            --file /lib/resolvconf/list-records
-ipsec attest --del --product "$p" --sha1                --file /usr/bin/lsb_release
-ipsec attest --del --product "$p" --sha1-ima            --file /usr/bin/lsb_release
-ipsec attest --del --product "$p" --sha1                --file /usr/share/language-tools/language-options
-ipsec attest --del --product "$p" --sha1-ima            --file /usr/share/language-tools/language-options
 
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_agent.c b/src/libpts/plugins/imv_attestation/imv_attestation_agent.c
index ae2660b..fcfee31 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_agent.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_agent.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011-2012 Sansar Choinyambuu
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -25,11 +25,15 @@
 #include <imcv.h>
 #include <imv/imv_agent.h>
 #include <imv/imv_msg.h>
+#include <imv/imv_session.h>
+#include <imv/imv_os_info.h>
 #include <ietf/ietf_attr.h>
 #include <ietf/ietf_attr_attr_request.h>
 #include <ietf/ietf_attr_pa_tnc_error.h>
 #include <ietf/ietf_attr_product_info.h>
 #include <ietf/ietf_attr_string_version.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_device_id.h>
 
 #include <libpts.h>
 
@@ -111,7 +115,9 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
 	private_imv_attestation_agent_t *this, TNC_ConnectionID id,
 	TNC_ConnectionState new_state)
 {
+	TNC_IMV_Action_Recommendation rec;
 	imv_state_t *state;
+	imv_session_t *session;
 
 	switch (new_state)
 	{
@@ -120,6 +126,35 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
 			return this->agent->create_state(this->agent, state);
 		case TNC_CONNECTION_STATE_DELETE:
 			return this->agent->delete_state(this->agent, id);
+		case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+		case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+		case TNC_CONNECTION_STATE_ACCESS_NONE:
+			if (this->agent->get_state(this->agent, id, &state) && imcv_db)
+			{
+				session = state->get_session(state);
+
+				if (session->get_policy_started(session))
+				{
+					switch (new_state)
+					{
+						case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+							rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+							break;
+						case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+							rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+							break;
+						case TNC_CONNECTION_STATE_ACCESS_NONE:
+						default:
+							rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+					}
+					imcv_db->add_recommendation(imcv_db, session, rec);
+					if (!imcv_db->policy_script(imcv_db, session, FALSE))
+					{
+						DBG1(DBG_IMV, "error in policy script stop");
+					}
+				}
+			}
+			/* fall through to default state */
 		default:
 			return this->agent->change_state(this->agent, id, new_state, NULL);
 	}
@@ -131,15 +166,14 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
 static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
 							  imv_state_t *state, imv_msg_t *in_msg)
 {
-	imv_attestation_state_t *attestation_state;
 	imv_msg_t *out_msg;
+	imv_session_t *session;
+	imv_os_info_t *os_info;
 	enumerator_t *enumerator;
 	pa_tnc_attr_t *attr;
 	pen_type_t type;
 	TNC_Result result;
-	pts_t *pts;
-	chunk_t os_name = chunk_empty;
-	chunk_t os_version = chunk_empty;
+	chunk_t os_name, os_version;
 	bool fatal_error = FALSE;
 
 	/* parse received PA-TNC message and handle local and remote errors */
@@ -149,8 +183,8 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
 		return result;
 	}
 
-	attestation_state = (imv_attestation_state_t*)state;
-	pts = attestation_state->get_pts(attestation_state);
+	session = state->get_session(state);
+	os_info = session->get_os_info(session);
 
 	out_msg = imv_msg_create_as_reply(in_msg);
 	out_msg->set_msg_type(out_msg, msg_types[0]);
@@ -188,17 +222,64 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
 				case IETF_ATTR_PRODUCT_INFORMATION:
 				{
 					ietf_attr_product_info_t *attr_cast;
+					pen_t vendor_id;
 
+					state->set_action_flags(state,
+										IMV_ATTESTATION_ATTR_PRODUCT_INFO);
 					attr_cast = (ietf_attr_product_info_t*)attr;
-					os_name = attr_cast->get_info(attr_cast, NULL, NULL);
+					os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
+					os_info->set_name(os_info, os_name);
+
+					if (vendor_id != PEN_IETF)
+					{
+						DBG1(DBG_IMV, "operating system name is '%.*s' "
+									  "from vendor %N", os_name.len, os_name.ptr,
+									   pen_names, vendor_id);
+					}
+					else
+					{
+						DBG1(DBG_IMV, "operating system name is '%.*s'",
+									   os_name.len, os_name.ptr);
+					}
+					break;
+
 					break;
 				}
 				case IETF_ATTR_STRING_VERSION:
 				{
 					ietf_attr_string_version_t *attr_cast;
 
+					state->set_action_flags(state,
+										IMV_ATTESTATION_ATTR_STRING_VERSION);
 					attr_cast = (ietf_attr_string_version_t*)attr;
 					os_version = attr_cast->get_version(attr_cast, NULL, NULL);
+					os_info->set_version(os_info, os_version);
+
+					if (os_version.len)
+					{
+						DBG1(DBG_IMV, "operating system version is '%.*s'",
+									   os_version.len, os_version.ptr);
+					}
+					break;
+				}
+				default:
+					break;
+			}
+		}
+		else if (type.vendor_id == PEN_ITA)
+		{
+			switch (type.type)
+			{
+				case ITA_ATTR_DEVICE_ID:
+				{
+					chunk_t value;
+
+					state->set_action_flags(state,
+										IMV_ATTESTATION_ATTR_DEVICE_ID);
+
+					value = attr->get_value(attr);
+					DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr);
+					session->set_device_id(session, value);
 					break;
 				}
 				default:
@@ -218,15 +299,6 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
 	}
 	enumerator->destroy(enumerator);
 
-	/**
-	 * The IETF Product Information and String Version attributes
-	 * are supposed to arrive in the same PA-TNC message
-	 */
-	if (os_name.len && os_version.len)
-	{
-		pts->set_platform_info(pts, os_name, os_version);
-	}
-
 	if (fatal_error || result != TNC_RESULT_SUCCESS)
 	{
 		state->set_recommendation(state,
@@ -288,6 +360,31 @@ METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
 	return result;
 }
 
+/**
+ * Build an IETF Attribute Request attribute for missing attributes
+ */
+static pa_tnc_attr_t* build_attr_request(uint32_t received)
+{
+	pa_tnc_attr_t *attr;
+	ietf_attr_attr_request_t *attr_cast;
+
+	attr = ietf_attr_attr_request_create(PEN_RESERVED, 0);
+	attr_cast = (ietf_attr_attr_request_t*)attr;
+
+	if (!(received & IMV_ATTESTATION_ATTR_PRODUCT_INFO) ||
+		!(received & IMV_ATTESTATION_ATTR_STRING_VERSION))
+	{
+		attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION);
+		attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION);
+	}
+	if (!(received & IMV_ATTESTATION_ATTR_DEVICE_ID))
+	{
+		attr_cast->add(attr_cast, PEN_ITA,  ITA_ATTR_DEVICE_ID);
+	}
+
+	return attr;
+}
+
 METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	private_imv_attestation_agent_t *this, TNC_ConnectionID id)
 {
@@ -302,7 +399,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	TNC_IMVID imv_id;
 	TNC_Result result = TNC_RESULT_SUCCESS;
 	pts_t *pts;
-	char *platform_info;
+	int pid;
+	uint32_t actions;
 	enumerator_t *enumerator;
 
 	if (!this->agent->get_state(this->agent, id, &state))
@@ -312,40 +410,59 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	attestation_state = (imv_attestation_state_t*)state;
 	pts = attestation_state->get_pts(attestation_state);
 	handshake_state = attestation_state->get_handshake_state(attestation_state);
-	platform_info = pts->get_platform_info(pts);
+	actions = state->get_action_flags(state);
 	session = state->get_session(state);
 	imv_id = this->agent->get_id(this->agent);
 
 	/* exit if a recommendation has already been provided */
-	if (state->get_action_flags(state) & IMV_ATTESTATION_FLAG_REC)
+	if (actions & IMV_ATTESTATION_REC)
 	{
 		return TNC_RESULT_SUCCESS;
 	}
 
 	/* send an IETF attribute request if no platform info was received */
-	if (!platform_info &&
-		!(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ATTR_REQ))
+	if (!(actions & IMV_ATTESTATION_ATTR_REQ))
 	{
-		pa_tnc_attr_t *attr;
-		ietf_attr_attr_request_t *attr_cast;
-		imv_msg_t *os_msg;
+		if ((actions & IMV_ATTESTATION_ATTR_MUST) != IMV_ATTESTATION_ATTR_MUST)
+		{
+			imv_msg_t *os_msg;
 
-		attr = ietf_attr_attr_request_create(PEN_IETF,
-											 IETF_ATTR_PRODUCT_INFORMATION);
-		attr_cast = (ietf_attr_attr_request_t*)attr;
-		attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION);
+			/* create attribute request for missing mandatory attributes */
+			os_msg = imv_msg_create(this->agent, state, id, imv_id,
+									TNC_IMCID_ANY, msg_types[1]);
+			os_msg->add_attribute(os_msg, build_attr_request(actions));
+			result = os_msg->send(os_msg, FALSE);
+			os_msg->destroy(os_msg);
 
-		os_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
-								 msg_types[1]);
-		os_msg->add_attribute(os_msg, attr);
-		result = os_msg->send(os_msg, FALSE);
-		os_msg->destroy(os_msg);
+			if (result != TNC_RESULT_SUCCESS)
+			{
+				return result;
+			}
+		 }
+		state->set_action_flags(state, IMV_ATTESTATION_ATTR_REQ);
+	}
 
-		if (result != TNC_RESULT_SUCCESS)
+	if (!session->get_policy_started(session) &&
+		(actions & IMV_ATTESTATION_ATTR_PRODUCT_INFO) &&
+		(actions & IMV_ATTESTATION_ATTR_STRING_VERSION) &&
+		(actions & IMV_ATTESTATION_ATTR_DEVICE_ID))
+	{
+		if (imcv_db)
 		{
-			return result;
+			/* start the policy script */
+			if (!imcv_db->policy_script(imcv_db, session, TRUE))
+			{
+				DBG1(DBG_IMV, "error in policy script start");
+			}
+		}
+		else
+		{
+			DBG2(DBG_IMV, "no workitems available - no evaluation possible");
+			state->set_recommendation(state,
+									  TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
+									  TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+			session->set_policy_started(session, TRUE);
 		}
-		state->set_action_flags(state, IMV_ATTESTATION_FLAG_ATTR_REQ);
 	}
 
 	if (handshake_state == IMV_ATTESTATION_STATE_INIT)
@@ -378,22 +495,24 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	}
 
 	/* exit if we are not ready yet for PTS measurements */
-	if (!platform_info || !session ||
-	    !(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ALGO))
+	if (!(actions & IMV_ATTESTATION_ALGO))
 	{
 		return TNC_RESULT_SUCCESS;
 	}
 
+	session->get_session_id(session, &pid, NULL);
+	pts->set_platform_id(pts, pid);
+
 	/* create an empty out message - we might need it */
 	out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
 							 msg_types[0]);
 
 	/* establish the PTS measurements to be taken */
-	if (!(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_FILE_MEAS))
+	if (!(actions & IMV_ATTESTATION_FILE_MEAS))
 	{
 		bool is_dir, no_workitems = TRUE;
-		u_int32_t delimiter = SOLIDUS_UTF;
-		u_int16_t request_id;
+		uint32_t delimiter = SOLIDUS_UTF;
+		uint16_t request_id;
 		pa_tnc_attr_t *attr;
 		char *pathname;
 
@@ -555,7 +674,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 			enumerator->destroy(enumerator);
 
 			/* sent all file and directory measurement and metadata requests */
-			state->set_action_flags(state, IMV_ATTESTATION_FLAG_FILE_MEAS);
+			state->set_action_flags(state, IMV_ATTESTATION_FILE_MEAS);
 
 			if (no_workitems)
 			{
@@ -600,14 +719,14 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	enumerator->destroy(enumerator);
 
 	/* finalized all workitems? */
-	if (session && session->get_policy_started(session) &&
+	if (session->get_policy_started(session) &&
 		session->get_workitem_count(session, imv_id) == 0 &&
 		attestation_state->get_handshake_state(attestation_state) ==
 			IMV_ATTESTATION_STATE_END)
 	{
 		result = out_msg->send_assessment(out_msg);
 		out_msg->destroy(out_msg);
-		state->set_action_flags(state, IMV_ATTESTATION_FLAG_REC);
+		state->set_action_flags(state, IMV_ATTESTATION_REC);
 
 		if (result != TNC_RESULT_SUCCESS)
 		{
@@ -642,14 +761,16 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
 	session = state->get_session(state);
 	imv_id = this->agent->get_id(this->agent);
 
-	if (session)
+	if (imcv_db)
 	{
 		TNC_IMV_Evaluation_Result eval;
 		TNC_IMV_Action_Recommendation rec;
 		imv_workitem_t *workitem;
 		enumerator_t *enumerator;
-		char *result_str;
 		int pending_file_meas = 0;
+		char *result_str;
+		chunk_t result_buf;
+		bio_writer_t *result;
 
 		enumerator = session->create_workitem_enumerator(session);
 		if (enumerator)
@@ -660,20 +781,28 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
 				{
 					continue;
 				}
+				result = bio_writer_create(128);
+
 				switch (workitem->get_type(workitem))
 				{
 					case IMV_WORKITEM_FILE_REF_MEAS:
 					case IMV_WORKITEM_FILE_MEAS:
 					case IMV_WORKITEM_DIR_REF_MEAS:
 					case IMV_WORKITEM_DIR_MEAS:
-						result_str = "Pending file measurements";
+						result_str = "pending file measurements";
 						pending_file_meas++;
 						break;
 					case IMV_WORKITEM_TPM_ATTEST:
-						attestation_state->finalize_components(attestation_state);
-						result_str = "Pending component evidence";
+						attestation_state->finalize_components(attestation_state,
+															   result);
+						result->write_data(result,
+								chunk_from_str("; pending component evidence"));
+						result->write_uint8(result, '\0');
+						result_buf = result->get_buf(result);
+						result_str = result_buf.ptr;
 						break;
 					default:
+						result->destroy(result);
 						continue;
 				}
 				session->remove_workitem(session, enumerator);
@@ -682,6 +811,7 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
 				state->update_recommendation(state, rec, eval);
 				imcv_db->finalize_workitem(imcv_db, workitem);
 				workitem->destroy(workitem);
+				result->destroy(result);
 			}
 			enumerator->destroy(enumerator);
 
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_build.c b/src/libpts/plugins/imv_attestation/imv_attestation_build.c
index 84023c6..120fe3e 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_build.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_build.c
@@ -62,6 +62,11 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
 			pts_meas_algorithms_t selected_algorithm;
 			chunk_t initiator_value, initiator_nonce;
 
+			if (!(state->get_action_flags(state) & IMV_ATTESTATION_DH_NONCE))
+			{
+				break;
+			}
+
 			/* Send DH nonce finish attribute */
 			selected_algorithm = pts->get_meas_algorithm(pts);
 			pts->get_my_public_value(pts, &initiator_value, &initiator_nonce);
@@ -89,17 +94,14 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
 			tcg_pts_attr_req_func_comp_evid_t *attr_cast;
 			enumerator_t *enumerator;
 			pts_comp_func_name_t *name;
-			chunk_t keyid;
-			int kid;
-			u_int8_t flags;
-			u_int32_t depth;
+			uint8_t flags;
+			uint32_t depth;
 			bool first_component = TRUE;
 
 			attestation_state->set_handshake_state(attestation_state,
 										IMV_ATTESTATION_STATE_END);
 
-			if (!pts->get_aik_keyid(pts, &keyid) ||
-				 pts_db->check_aik_keyid(pts_db, keyid, &kid) != SUCCESS)
+			if (!pts->get_aik_id(pts))
 			{
 				attestation_state->set_measurement_error(attestation_state,
 									IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_process.c b/src/libpts/plugins/imv_attestation/imv_attestation_process.c
index e40c92a..26a57d1 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_process.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_process.c
@@ -46,10 +46,12 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 							 pts_database_t *pts_db,
 							 credential_manager_t *pts_credmgr)
 {
+	imv_session_t *session;
 	imv_attestation_state_t *attestation_state;
 	pen_type_t attr_type;
 	pts_t *pts;
 
+	session = state->get_session(state);
 	attestation_state = (imv_attestation_state_t*)state;
 	pts = attestation_state->get_pts(attestation_state);
 	attr_type = attr->get_type(attr);
@@ -80,7 +82,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 				return FALSE;
 			}
 			pts->set_meas_algorithm(pts, selected_algorithm);
-			state->set_action_flags(state, IMV_ATTESTATION_FLAG_ALGO);
+			state->set_action_flags(state, IMV_ATTESTATION_ALGO);
 			break;
 		}
 		case TCG_PTS_DH_NONCE_PARAMS_RESP:
@@ -140,6 +142,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 			{
 				return FALSE;
 			}
+			state->set_action_flags(state, IMV_ATTESTATION_DH_NONCE);
 			break;
 		}
 		case TCG_PTS_TPM_VERSION_INFO:
@@ -157,9 +160,10 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 			tcg_pts_attr_aik_t *attr_cast;
 			certificate_t *aik, *issuer;
 			public_key_t *public;
-			chunk_t keyid;
+			chunk_t keyid, keyid_hex, device_id;
+			int aik_id;
 			enumerator_t *e;
-			bool trusted = FALSE;
+			bool trusted = FALSE, trusted_chain = FALSE;
 
 			attr_cast = (tcg_pts_attr_aik_t*)attr;
 			aik = attr_cast->get_aik(attr_cast);
@@ -170,12 +174,27 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 									IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
 				break;
 			}
+
+			/* check trust into public key as stored in the database */
+			public = aik->get_public_key(aik);
+			public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid);
+			DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid);
+			keyid_hex = chunk_to_hex(keyid, NULL, FALSE);
+			if (session->get_device_id(session, &device_id) &&
+				chunk_equals(keyid_hex, device_id))
+			{
+				trusted = session->get_device_trust(session);
+			}
+			else
+			{
+				DBG1(DBG_IMV, "device ID unknown or different from AIK keyid");
+			}
+			DBG1(DBG_IMV, "AIK public key is %strusted", trusted ? "" : "not ");
+			public->destroy(public);
+			chunk_free(&keyid_hex);
+
 			if (aik->get_type(aik) == CERT_X509)
 			{
-				public = aik->get_public_key(aik);
-				public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid);
-				DBG1(DBG_IMV, "verifying AIK certificate with keyid %#B", &keyid);
-				public->destroy(public);
 
 				e = pts_credmgr->create_trusted_enumerator(pts_credmgr,
 							KEY_ANY, aik->get_issuer(aik), FALSE);
@@ -183,21 +202,22 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 				{
 					if (aik->issued_by(aik, issuer, NULL))
 					{
-						trusted = TRUE;
+						trusted_chain = TRUE;
 						break;
 					}
 				}
 				e->destroy(e);
 				DBG1(DBG_IMV, "AIK certificate is %strusted",
-							   trusted ? "" : "not ");
-				if (!trusted)
+							   trusted_chain ? "" : "not ");
+				if (!trusted || !trusted_chain)
 				{
 					attestation_state->set_measurement_error(attestation_state,
 										IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
 					break;
 				}
 			}
-			pts->set_aik(pts, aik);
+			session->get_session_id(session, NULL, &aik_id);
+			pts->set_aik(pts, aik, aik_id);
 			break;
 		}
 		case TCG_PTS_FILE_MEAS:
@@ -205,21 +225,18 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 			TNC_IMV_Evaluation_Result eval;
 			TNC_IMV_Action_Recommendation rec;
 			tcg_pts_attr_file_meas_t *attr_cast;
-			u_int16_t request_id;
+			uint16_t request_id;
 			int arg_int, file_count;
 			pts_meas_algorithms_t algo;
 			pts_file_meas_t *measurements;
-			imv_session_t *session;
 			imv_workitem_t *workitem, *found = NULL;
 			imv_workitem_type_t type;
-			char result_str[BUF_LEN], *platform_info;
+			char result_str[BUF_LEN];
 			bool is_dir, correct;
 			enumerator_t *enumerator;
 
 			eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
-			session = state->get_session(state);
 			algo = pts->get_meas_algorithm(pts);
-			platform_info = pts->get_platform_info(pts);
 			attr_cast = (tcg_pts_attr_file_meas_t*)attr;
 			measurements = attr_cast->get_measurements(attr_cast);
 			request_id = measurements->get_request_id(measurements);
@@ -272,7 +289,8 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 
 						/* check hashes from database against measurements */
 						e = pts_db->create_file_hash_enumerator(pts_db,
-										platform_info, algo, is_dir, arg_int);
+											pts->get_platform_id(pts), 
+											algo, is_dir, arg_int);
 						if (!e)
 						{
 							eval = TNC_IMV_EVALUATION_RESULT_ERROR;
@@ -304,8 +322,8 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 						while (e->enumerate(e, &filename, &measurement))
 						{
 							if (pts_db->add_file_measurement(pts_db,
-									platform_info, algo, measurement, filename,
-									is_dir, arg_int) != SUCCESS)
+									pts->get_platform_id(pts), algo, measurement,
+									filename, is_dir, arg_int) != SUCCESS)
 							{
 								eval = TNC_IMV_EVALUATION_RESULT_ERROR;
 							}
@@ -328,7 +346,8 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 			}
 			else
 			{
-				measurements->check(measurements, pts_db, platform_info, algo);
+				measurements->check(measurements, pts_db,
+									pts->get_platform_id(pts), algo);
 			}
 			break;
 		}
@@ -373,7 +392,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 			pts_comp_func_name_t *name;
 			pts_comp_evidence_t *evidence;
 			pts_component_t *comp;
-			u_int32_t depth;
+			uint32_t depth;
 			status_t status;
 
 			attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr;
@@ -398,14 +417,15 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 		case TCG_PTS_SIMPLE_EVID_FINAL:
 		{
 			tcg_pts_attr_simple_evid_final_t *attr_cast;
-			u_int8_t flags;
+			uint8_t flags;
 			pts_meas_algorithms_t comp_hash_algorithm;
 			chunk_t pcr_comp, tpm_quote_sig, evid_sig;
-			chunk_t pcr_composite, quote_info;
-			imv_session_t *session;
+			chunk_t pcr_composite, quote_info, result_buf;
 			imv_workitem_t *workitem;
+			imv_reason_string_t *reason_string;
 			enumerator_t *enumerator;
 			bool use_quote2, use_ver_info;
+			bio_writer_t *result;
 
 			attr_cast = (tcg_pts_attr_simple_evid_final_t*)attr;
 			flags = attr_cast->get_quote_info(attr_cast, &comp_hash_algorithm,
@@ -451,9 +471,10 @@ quote_error:
 				 * Finalize any pending measurement registrations and check
 				 * if all expected component measurements were received
 				 */
-				attestation_state->finalize_components(attestation_state);
+				result = bio_writer_create(128);
+				attestation_state->finalize_components(attestation_state,
+													   result);
 
-				session = state->get_session(state);
 				enumerator = session->create_workitem_enumerator(session);
 				while (enumerator->enumerate(enumerator, &workitem))
 				{
@@ -461,8 +482,7 @@ quote_error:
 					{
 						TNC_IMV_Action_Recommendation rec;
 						TNC_IMV_Evaluation_Result eval;
-						char *result_str;
-						u_int32_t error;
+						uint32_t error;
 
 						error = attestation_state->get_measurement_error(
 														attestation_state);
@@ -470,34 +490,35 @@ quote_error:
 									 IMV_ATTESTATION_ERROR_COMP_EVID_PEND |
 									 IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL))
 						{
-							imv_reason_string_t *reason_string;
-							chunk_t result;
-
 							reason_string = imv_reason_string_create("en", ", ");
 							attestation_state->add_comp_evid_reasons(
 											attestation_state, reason_string);
-							result = reason_string->get_encoding(reason_string);
-							result_str = strndup(result.ptr, result.len);
+							result->write_data(result, chunk_from_str("; "));
+							result->write_data(result,
+									reason_string->get_encoding(reason_string));
 							reason_string->destroy(reason_string);
 							eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
 						}
 						else
 						{
-							result_str = strdup("attestation successful");
 							eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
 						}
 						session->remove_workitem(session, enumerator);
-						rec = workitem->set_result(workitem, result_str, eval);
+
+						result->write_uint8(result, '\0');
+						result_buf = result->get_buf(result);
+						rec = workitem->set_result(workitem, result_buf.ptr,
+															 eval);
 						state->update_recommendation(state, rec, eval);
 						imcv_db->finalize_workitem(imcv_db, workitem);
 						workitem->destroy(workitem);
-						free(result_str);
 						attestation_state->set_handshake_state(attestation_state,
 													IMV_ATTESTATION_STATE_END);
 						break;
 					}
 				}
 				enumerator->destroy(enumerator);
+				result->destroy(result);
 			}
 
 			if (attr_cast->get_evid_sig(attr_cast, &evid_sig))
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c
index 9304b9a..11afbc2 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c
@@ -63,22 +63,12 @@ struct private_imv_attestation_state_t {
 	/**
 	 * Maximum PA-TNC message size for this TNCCS connection
 	 */
-	u_int32_t max_msg_len;
+	uint32_t max_msg_len;
 
 	/**
 	 * Flags set for completed actions
 	 */
-	u_int32_t action_flags;
-
-	/**
-	 * Access Requestor ID Type
-	 */
-	u_int32_t ar_id_type;
-
-	/**
-	 * Access Requestor ID Value
-	 */
-	chunk_t ar_id_value;
+	uint32_t action_flags;
 
 	/**
 	 * IMV database session associated with TNCCS connection
@@ -113,7 +103,7 @@ struct private_imv_attestation_state_t {
 	/**
 	 * Measurement error flags
 	 */
-	u_int32_t measurement_error;
+	uint32_t measurement_error;
 
 	/**
 	 * TNC Reason String
@@ -215,46 +205,29 @@ METHOD(imv_state_t, set_flags, void,
 }
 
 METHOD(imv_state_t, set_max_msg_len, void,
-	private_imv_attestation_state_t *this, u_int32_t max_msg_len)
+	private_imv_attestation_state_t *this, uint32_t max_msg_len)
 {
 	this->max_msg_len = max_msg_len;
 }
 
-METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
 	private_imv_attestation_state_t *this)
 {
 	return this->max_msg_len;
 }
 
 METHOD(imv_state_t, set_action_flags, void,
-	private_imv_attestation_state_t *this, u_int32_t flags)
+	private_imv_attestation_state_t *this, uint32_t flags)
 {
 	this->action_flags |= flags;
 }
 
-METHOD(imv_state_t, get_action_flags, u_int32_t,
+METHOD(imv_state_t, get_action_flags, uint32_t,
 	private_imv_attestation_state_t *this)
 {
 	return this->action_flags;
 }
 
-METHOD(imv_state_t, set_ar_id, void,
-	private_imv_attestation_state_t *this, u_int32_t id_type, chunk_t id_value)
-{
-	this->ar_id_type = id_type;
-	this->ar_id_value = chunk_clone(id_value);
-}
-
-METHOD(imv_state_t, get_ar_id, chunk_t,
-	private_imv_attestation_state_t *this, u_int32_t *id_type)
-{
-	if (id_type)
-	{
-		*id_type = this->ar_id_type;
-	}
-	return this->ar_id_value;
-}
-
 METHOD(imv_state_t, set_session, void,
 	private_imv_attestation_state_t *this, imv_session_t *session)
 {
@@ -362,7 +335,6 @@ METHOD(imv_state_t, destroy, void,
 	DESTROY_IF(this->reason_string);
 	this->components->destroy_function(this->components, (void *)free_func_comp);
 	this->pts->destroy(this->pts);
-	free(this->ar_id_value.ptr);
 	free(this);
 }
 
@@ -387,7 +359,7 @@ METHOD(imv_attestation_state_t, get_pts, pts_t*,
 
 METHOD(imv_attestation_state_t, create_component, pts_component_t*,
 	private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
-	u_int32_t depth, pts_database_t *pts_db)
+	uint32_t depth, pts_database_t *pts_db)
 {
 	enumerator_t *enumerator;
 	func_comp_t *entry, *new_entry;
@@ -437,8 +409,8 @@ METHOD(imv_attestation_state_t, create_component, pts_component_t*,
 /**
  * Enumerate file measurement entries
  */
-static bool entry_filter(void *null, func_comp_t **entry, u_int8_t *flags,
-						 void *i2, u_int32_t *depth,
+static bool entry_filter(void *null, func_comp_t **entry, uint8_t *flags,
+						 void *i2, uint32_t *depth,
 						 void *i3, pts_comp_func_name_t **comp_name)
 {
 	pts_component_t *comp;
@@ -482,28 +454,38 @@ METHOD(imv_attestation_state_t, get_component, pts_component_t*,
 	return found;
 }
 
-METHOD(imv_attestation_state_t, get_measurement_error, u_int32_t,
+METHOD(imv_attestation_state_t, get_measurement_error, uint32_t,
 	private_imv_attestation_state_t *this)
 {
 	return this->measurement_error;
 }
 
 METHOD(imv_attestation_state_t, set_measurement_error, void,
-	private_imv_attestation_state_t *this, u_int32_t error)
+	private_imv_attestation_state_t *this, uint32_t error)
 {
 	this->measurement_error |= error;
 }
 
 METHOD(imv_attestation_state_t, finalize_components, void,
-	private_imv_attestation_state_t *this)
+	private_imv_attestation_state_t *this, bio_writer_t *result)
 {
 	func_comp_t *entry;
+	bool first = TRUE;
 
 	while (this->components->remove_last(this->components,
 										(void**)&entry) == SUCCESS)
 	{
+		if (first)
+		{
+			first = FALSE;
+		}
+		else
+		{
+			result->write_data(result, chunk_from_str("; "));
+		}
 		if (!entry->comp->finalize(entry->comp,
-								   entry->name->get_qualifier(entry->name)))
+								   entry->name->get_qualifier(entry->name),
+								   result))
 		{
 			set_measurement_error(this, IMV_ATTESTATION_ERROR_COMP_EVID_PEND);
 		}
@@ -529,8 +511,6 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
 				.get_max_msg_len = _get_max_msg_len,
 				.set_action_flags = _set_action_flags,
 				.get_action_flags = _get_action_flags,
-				.set_ar_id = _set_ar_id,
-				.get_ar_id = _get_ar_id,
 				.set_session = _set_session,
 				.get_session = _get_session,
 				.change_state = _change_state,
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.h b/src/libpts/plugins/imv_attestation/imv_attestation_state.h
index 9369d30..b728575 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_state.h
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.h
@@ -29,7 +29,9 @@
 #include <pts/pts.h>
 #include <pts/pts_database.h>
 #include <pts/components/pts_component.h>
+
 #include <library.h>
+#include <bio/bio_writer.h>
 
 typedef struct imv_attestation_state_t imv_attestation_state_t;
 typedef enum imv_attestation_flag_t imv_attestation_flag_t;
@@ -40,10 +42,15 @@ typedef enum imv_meas_error_t imv_meas_error_t;
  * IMV Attestation Flags set for completed actions
  */
 enum imv_attestation_flag_t {
-	IMV_ATTESTATION_FLAG_ATTR_REQ =  (1<<0),
-	IMV_ATTESTATION_FLAG_ALGO =      (1<<1),
-	IMV_ATTESTATION_FLAG_FILE_MEAS = (1<<2),
-	IMV_ATTESTATION_FLAG_REC =       (1<<3)
+	IMV_ATTESTATION_ATTR_PRODUCT_INFO =   (1<<0),
+	IMV_ATTESTATION_ATTR_STRING_VERSION = (1<<1),
+	IMV_ATTESTATION_ATTR_DEVICE_ID =      (1<<2),
+	IMV_ATTESTATION_ATTR_MUST =           (1<<3)-1,
+	IMV_ATTESTATION_ATTR_REQ =            (1<<3),
+	IMV_ATTESTATION_ALGO =                (1<<4),
+	IMV_ATTESTATION_DH_NONCE =            (1<<5),
+	IMV_ATTESTATION_FILE_MEAS =           (1<<6),
+	IMV_ATTESTATION_REC =                 (1<<7)
 };
 
 /**
@@ -114,7 +121,7 @@ struct imv_attestation_state_t {
 	 */
 	pts_component_t* (*create_component)(imv_attestation_state_t *this,
 										 pts_comp_func_name_t *name,
-										 u_int32_t depth,
+										 uint32_t depth,
 										 pts_database_t *pts_db);
 
 	/**
@@ -136,15 +143,18 @@ struct imv_attestation_state_t {
 	/**
 	 * Tell the Functional Components to finalize any measurement registrations
 	 * and to check if all expected measurements were received
+	 *
+	 * @param result			Writer appending component measurement results
 	 */
-	void (*finalize_components)(imv_attestation_state_t *this);
+	void (*finalize_components)(imv_attestation_state_t *this,
+								bio_writer_t *result);
 
 	/**
 	 * Indicates the types of measurement errors that occurred
 	 *
 	 * @return					Measurement error flags
 	 */
-	u_int32_t (*get_measurement_error)(imv_attestation_state_t *this);
+	uint32_t (*get_measurement_error)(imv_attestation_state_t *this);
 
 	/**
 	 * Call if a measurement error is encountered
@@ -152,7 +162,7 @@ struct imv_attestation_state_t {
 	 * @param error				Measurement error type
 	 */
 	void (*set_measurement_error)(imv_attestation_state_t *this,
-								  u_int32_t error);
+								  uint32_t error);
 
 	/**
 	 * Returns a concatenation of File Measurement reason strings
diff --git a/src/libpts/plugins/imv_swid/Makefile.am b/src/libpts/plugins/imv_swid/Makefile.am
index 29c05e0..77f33e6 100644
--- a/src/libpts/plugins/imv_swid/Makefile.am
+++ b/src/libpts/plugins/imv_swid/Makefile.am
@@ -5,17 +5,19 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libpts
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-swid.la
 
 imv_swid_la_LIBADD = \
 	$(top_builddir)/src/libimcv/libimcv.la \
 	$(top_builddir)/src/libpts/libpts.la \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	-ljson
 
 imv_swid_la_SOURCES = \
 	imv_swid.c imv_swid_state.h imv_swid_state.c \
-	imv_swid_agent.h imv_swid_agent.c
+	imv_swid_agent.h imv_swid_agent.c \
+	imv_swid_rest.h imv_swid_rest.c
 
 imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/src/libpts/plugins/imv_swid/Makefile.in b/src/libpts/plugins/imv_swid/Makefile.in
index f9bd93c..bd89a6f 100644
--- a/src/libpts/plugins/imv_swid/Makefile.in
+++ b/src/libpts/plugins/imv_swid/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -131,7 +131,7 @@ imv_swid_la_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
 	$(top_builddir)/src/libpts/libpts.la \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la
 am_imv_swid_la_OBJECTS = imv_swid.lo imv_swid_state.lo \
-	imv_swid_agent.lo
+	imv_swid_agent.lo imv_swid_rest.lo
 imv_swid_la_OBJECTS = $(am_imv_swid_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,17 +420,19 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libpts
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 imcv_LTLIBRARIES = imv-swid.la
 imv_swid_la_LIBADD = \
 	$(top_builddir)/src/libimcv/libimcv.la \
 	$(top_builddir)/src/libpts/libpts.la \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	-ljson
 
 imv_swid_la_SOURCES = \
 	imv_swid.c imv_swid_state.h imv_swid_state.c \
-	imv_swid_agent.h imv_swid_agent.c
+	imv_swid_agent.h imv_swid_agent.c \
+	imv_swid_rest.h imv_swid_rest.c
 
 imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
 all: all-am
@@ -510,6 +516,7 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/imv_swid.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/imv_swid_agent.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/imv_swid_rest.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/imv_swid_state.Plo at am__quote@
 
 .c.o:
diff --git a/src/libpts/plugins/imv_swid/imv_swid_agent.c b/src/libpts/plugins/imv_swid/imv_swid_agent.c
index a0326f8..3053b26 100644
--- a/src/libpts/plugins/imv_swid/imv_swid_agent.c
+++ b/src/libpts/plugins/imv_swid/imv_swid_agent.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -13,8 +13,12 @@
  * for more details.
  */
 
+#define _GNU_SOURCE
+#include <stdio.h>
+
 #include "imv_swid_agent.h"
 #include "imv_swid_state.h"
+#include "imv_swid_rest.h"
 
 #include "libpts.h"
 #include "swid/swid_error.h"
@@ -27,6 +31,8 @@
 #include <ietf/ietf_attr_pa_tnc_error.h>
 #include <imv/imv_agent.h>
 #include <imv/imv_msg.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_angel.h>
 
 #include <tncif_names.h>
 #include <tncif_pa_subtypes.h>
@@ -43,6 +49,14 @@ static pen_type_t msg_types[] = {
 };
 
 /**
+ * Flag set when corresponding attribute has been received
+ */
+enum imv_swid_attr_t {
+	IMV_SWID_ATTR_TAG_INV =    (1<<0),
+	IMV_SWID_ATTR_TAG_ID_INV = (1<<1)
+};
+
+/**
  * Private data of an imv_swid_agent_t object.
  */
 struct private_imv_swid_agent_t {
@@ -57,6 +71,11 @@ struct private_imv_swid_agent_t {
 	 */
 	imv_agent_t *agent;
 
+	/**
+	 * REST API to strongTNC manager
+	 */
+	imv_swid_rest_t *rest_api;
+
 };
 
 METHOD(imv_agent_if_t, bind_functions, TNC_Result,
@@ -89,8 +108,8 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
 static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 							  imv_state_t *state, imv_msg_t *in_msg)
 {
+	imv_swid_state_t *swid_state;
 	imv_msg_t *out_msg;
-	imv_session_t *session;
 	enumerator_t *enumerator;
 	pa_tnc_attr_t *attr;
 	TNC_Result result;
@@ -103,22 +122,16 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 		return result;
 	}
 
-	session = state->get_session(state);
+	swid_state = (imv_swid_state_t*)state;
 
 	/* analyze PA-TNC attributes */
 	enumerator = in_msg->create_attribute_enumerator(in_msg);
 	while (enumerator->enumerate(enumerator, &attr))
 	{
-		TNC_IMV_Evaluation_Result eval;
-		TNC_IMV_Action_Recommendation rec;
-		pen_type_t type;
-		u_int32_t request_id, last_eid, eid_epoch;
+		uint32_t request_id = 0, last_eid, eid_epoch;
 		swid_inventory_t *inventory;
-		int tag_count;
-		char result_str[BUF_LEN], *tag_item;
-		imv_workitem_t *workitem, *found = NULL;
-		enumerator_t *et, *ew;
-		
+		pen_type_t type;
+
 		type = attr->get_type(attr);
 
 		if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
@@ -127,7 +140,7 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 			pen_type_t error_code;
 			chunk_t msg_info, description;
 			bio_reader_t *reader;
-			u_int32_t request_id = 0, max_attr_size;
+			uint32_t max_attr_size;
 			bool success;
 
 			error_attr = (ietf_attr_pa_tnc_error_t*)attr;
@@ -166,6 +179,20 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 				reader->destroy(reader);
 			}
 		}
+		else if (type.vendor_id == PEN_ITA)
+		{
+			switch (type.type)
+			{
+				case ITA_ATTR_START_ANGEL:
+					swid_state->set_angel_count(swid_state, TRUE);
+					continue;
+				case ITA_ATTR_STOP_ANGEL:
+					swid_state->set_angel_count(swid_state, FALSE);
+					continue;
+				default:
+					continue;
+			}
+		}
 		else if (type.vendor_id != PEN_TCG)
 		{
 			continue;
@@ -176,33 +203,30 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 			case TCG_SWID_TAG_ID_INVENTORY:
 			{
 				tcg_swid_attr_tag_id_inv_t *attr_cast;
-				swid_tag_id_t *tag_id;
-				chunk_t tag_creator, unique_sw_id;
+				int tag_id_count;
+
+				state->set_action_flags(state, IMV_SWID_ATTR_TAG_ID_INV);
 
 				attr_cast = (tcg_swid_attr_tag_id_inv_t*)attr;
 				request_id = attr_cast->get_request_id(attr_cast);
 				last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
 				inventory = attr_cast->get_inventory(attr_cast);
-				tag_item = "tag ID";
-				DBG2(DBG_IMV, "received SWID %s inventory for request %d "
-							  "at eid %d of epoch 0x%08x", tag_item,
+				tag_id_count = inventory->get_count(inventory);
+
+				DBG2(DBG_IMV, "received SWID tag ID inventory with %d item%s "
+							  "for request %d at eid %d of epoch 0x%08x",
+							   tag_id_count, (tag_id_count == 1) ? "" : "s",
 							   request_id, last_eid, eid_epoch);
 
-				et = inventory->create_enumerator(inventory);
-				while (et->enumerate(et, &tag_id))
+				if (request_id == swid_state->get_request_id(swid_state))
 				{
-					tag_creator = tag_id->get_tag_creator(tag_id);
-					unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
-					DBG3(DBG_IMV, "  %.*s_%.*s.swidtag",
-						 tag_creator.len, tag_creator.ptr,
-						 unique_sw_id.len, unique_sw_id.ptr);
+					swid_state->set_swid_inventory(swid_state, inventory);
+					swid_state->set_count(swid_state, tag_id_count, 0);
 				}
-				et->destroy(et);
-
-				if (request_id == 0)
+				else
 				{
-					/* TODO handle subscribed messages */
-					break;
+					DBG1(DBG_IMV, "no workitem found for SWID tag ID inventory "
+								  "with request ID %d", request_id);
 				}
 				break;
 			 }
@@ -211,62 +235,64 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
 				tcg_swid_attr_tag_inv_t *attr_cast;
 				swid_tag_t *tag;
 				chunk_t tag_encoding;
+				json_object *jobj, *jarray, *jstring;
+				char *tag_str;
+				int tag_count;
+				enumerator_t *e;
+
+				state->set_action_flags(state, IMV_SWID_ATTR_TAG_INV);
 
 				attr_cast = (tcg_swid_attr_tag_inv_t*)attr;
 				request_id = attr_cast->get_request_id(attr_cast);
 				last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
 				inventory = attr_cast->get_inventory(attr_cast);
-				tag_item = "tag";
-				DBG2(DBG_IMV, "received SWID %s inventory for request %d "
-							  "at eid %d of epoch 0x%08x", tag_item,
+				tag_count = inventory->get_count(inventory);
+
+				DBG2(DBG_IMV, "received SWID tag inventory with %d item%s for "
+							  "request %d at eid %d of epoch 0x%08x",
+							   tag_count, (tag_count == 1) ? "" : "s",
 							   request_id, last_eid, eid_epoch);
 
-				et = inventory->create_enumerator(inventory);
-				while (et->enumerate(et, &tag))
+
+				if (request_id == swid_state->get_request_id(swid_state))
 				{
-					tag_encoding = tag->get_encoding(tag);
-					DBG3(DBG_IMV, "%.*s", tag_encoding.len, tag_encoding.ptr);
-				}
-				et->destroy(et);
+					swid_state->set_count(swid_state, 0, tag_count);
 
-				if (request_id == 0)
+					if (this->rest_api)
+					{
+						jobj = json_object_new_object();
+						jarray = json_object_new_array();
+						json_object_object_add(jobj, "data", jarray);
+
+						e = inventory->create_enumerator(inventory);
+						while (e->enumerate(e, &tag))
+						{
+							tag_encoding = tag->get_encoding(tag);
+							tag_str = strndup(tag_encoding.ptr, tag_encoding.len);
+							DBG3(DBG_IMV, "%s", tag_str);
+							jstring = json_object_new_string(tag_str);
+							json_object_array_add(jarray, jstring);
+							free(tag_str);
+						}
+						e->destroy(e);
+
+						if (this->rest_api->post(this->rest_api,
+								"swid/add-tags/", jobj, NULL) != SUCCESS)
+						{
+							DBG1(DBG_IMV, "error in REST API add-tags request");
+						}
+						json_object_put(jobj);
+					}
+				}
+				else
 				{
-					/* TODO handle subscribed messages */
-					break;
+					DBG1(DBG_IMV, "no workitem found for SWID tag inventory "
+								  "with request ID %d", request_id);
 				}
-				break;
 			}
 			default:
 				continue;
 		 }
-
-		ew = session->create_workitem_enumerator(session);
-		while (ew->enumerate(ew, &workitem))
-		{
-			if (workitem->get_id(workitem) == request_id)
-			{
-				found = workitem;
-				break;
-			}
-		}
-		if (!found)
-		{
-			DBG1(DBG_IMV, "no workitem found for SWID %s inventory "
-						  "with request ID %d", tag_item, request_id);
-			ew->destroy(ew);
-			continue;
-		}
-
-		eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
-		tag_count = inventory->get_count(inventory);
-		snprintf(result_str, BUF_LEN, "received inventory of %d SWID %s%s",
-				 tag_count, tag_item, (tag_count == 1) ? "" : "s");
-		session->remove_workitem(session, ew);
-		ew->destroy(ew);
-		rec = found->set_result(found, result_str, eval);
-		state->update_recommendation(state, rec, eval);
-		imcv_db->finalize_workitem(imcv_db, found);
-		found->destroy(found);
 	}
 	enumerator->destroy(enumerator);
 
@@ -342,8 +368,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 	TNC_IMVID imv_id;
 	TNC_Result result = TNC_RESULT_SUCCESS;
 	bool no_workitems = TRUE;
-	u_int32_t request_id;
-	u_int8_t flags;
+	uint32_t request_id, received;
+	uint8_t flags;
 	enumerator_t *enumerator;
 
 	if (!this->agent->get_state(this->agent, id, &state))
@@ -360,11 +386,11 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 		return TNC_RESULT_SUCCESS;
 	}
 
-	/* create an empty out message - we might need it */
+	/* Create an empty out message - we might need it */
 	out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
 							 msg_types[0]);
 
-	if (!session)
+	if (!imcv_db)
 	{
 		DBG2(DBG_IMV, "no workitems available - no evaluation possible");
 		state->set_recommendation(state,
@@ -381,7 +407,9 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 		return this->agent->provide_recommendation(this->agent, state);
 	}
 
-	if (handshake_state == IMV_SWID_STATE_INIT)
+	/* Look for SWID tag workitem and create SWID tag request */
+	if (handshake_state == IMV_SWID_STATE_INIT &&
+		session->get_policy_started(session))
 	{
 		enumerator = session->create_workitem_enumerator(session);
 		if (enumerator)
@@ -408,13 +436,14 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 					flags |= TCG_SWID_ATTR_REQ_FLAG_C;
 				}
 				request_id = workitem->get_id(workitem);
-
+				swid_state->set_request_id(swid_state, request_id);
 				attr = tcg_swid_attr_req_create(flags, request_id, 0);
 				out_msg->add_attribute(out_msg, attr);
 				workitem->set_imv_id(workitem, imv_id);
 				no_workitems = FALSE;
 				DBG2(DBG_IMV, "IMV %d issues SWID request %d",
 						 imv_id, request_id);
+				break;
 			}
 			enumerator->destroy(enumerator);
 
@@ -431,6 +460,171 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
 		}
 	}
 
+	received = state->get_action_flags(state);
+
+	if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
+	   (received & (IMV_SWID_ATTR_TAG_INV|IMV_SWID_ATTR_TAG_ID_INV)) &&
+		swid_state->get_angel_count(swid_state) <= 0)
+	{
+		TNC_IMV_Evaluation_Result eval;
+		TNC_IMV_Action_Recommendation rec;
+		char result_str[BUF_LEN], *error_str = "", *command;
+		char *target, *separator;
+		int tag_id_count, tag_count, i;
+		size_t max_attr_size, attr_size, entry_size;
+		chunk_t tag_creator, unique_sw_id;
+		json_object *jrequest, *jresponse, *jvalue;
+		tcg_swid_attr_req_t *cast_attr;
+		swid_tag_id_t *tag_id;
+		status_t status = SUCCESS;
+
+		if (this->rest_api && (received & IMV_SWID_ATTR_TAG_ID_INV))
+		{
+			if (asprintf(&command, "sessions/%d/swid-measurement/",
+						 session->get_session_id(session, NULL, NULL)) < 0)
+			{
+				error_str = "allocation of command string failed";
+				status = FAILED;
+			}
+			else
+			{
+				jrequest = swid_state->get_swid_inventory(swid_state);
+				status = this->rest_api->post(this->rest_api, command,
+											  jrequest, &jresponse);
+				if (status == FAILED)
+				{
+					error_str = "error in REST API swid-measurement request";
+				}
+				free(command);
+			}
+		}
+
+		switch (status)
+		{
+			case SUCCESS:
+				enumerator = session->create_workitem_enumerator(session);
+				while (enumerator->enumerate(enumerator, &workitem))
+				{
+					if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
+					{
+						swid_state->get_count(swid_state, &tag_id_count,
+														  &tag_count);
+						snprintf(result_str, BUF_LEN, "received inventory of "
+								 "%d SWID tag ID%s and %d SWID tag%s",
+								 tag_id_count, (tag_id_count == 1) ? "" : "s",
+								 tag_count, (tag_count == 1) ? "" : "s");
+						session->remove_workitem(session, enumerator);
+
+						eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
+						rec = workitem->set_result(workitem, result_str, eval);
+						state->update_recommendation(state, rec, eval);
+						imcv_db->finalize_workitem(imcv_db, workitem);
+						workitem->destroy(workitem);
+						break;
+					}
+				}
+				enumerator->destroy(enumerator);
+				break;
+			case NEED_MORE:
+				if (received & IMV_SWID_ATTR_TAG_INV)
+				{
+					error_str = "not all requested SWID tags were received";
+					status = FAILED;
+					json_object_put(jresponse);
+					break;
+				}
+				if (json_object_get_type(jresponse) != json_type_array)
+				{
+					error_str = "response was not a json_array";
+					status = FAILED;
+					json_object_put(jresponse);
+					break;
+				}
+
+				/* Compute the maximum TCG SWID Request attribute size */
+				max_attr_size = state->get_max_msg_len(state) -
+								PA_TNC_HEADER_SIZE;
+
+				/* Create the [first] TCG SWID Request attribute */
+				attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_REQ_MIN_SIZE;			
+				attr = tcg_swid_attr_req_create(TCG_SWID_ATTR_REQ_FLAG_NONE,
+								swid_state->get_request_id(swid_state), 0);
+
+				tag_id_count = json_object_array_length(jresponse);
+				DBG1(DBG_IMV, "%d SWID tag target%s", tag_id_count,
+							  (tag_id_count == 1) ? "" : "s");
+
+				for (i = 0; i < tag_id_count; i++)
+				{
+					jvalue = json_object_array_get_idx(jresponse, i);
+					if (json_object_get_type(jvalue) != json_type_string)
+					{
+						error_str = "json_string element expected in json_array";
+						status = FAILED;
+						json_object_put(jresponse);
+						break;
+					}
+					target = (char*)json_object_get_string(jvalue);
+					DBG1(DBG_IMV, "  %s", target);
+
+					/* Separate target into tag_creator and unique_sw_id */
+					separator = strchr(target, '_');
+					if (!separator)
+					{
+						error_str = "separation of regid from "
+									"unique software ID failed";
+						break;
+					}
+					tag_creator = chunk_create(target, separator - target);
+					separator++;
+					unique_sw_id = chunk_create(separator, strlen(target) -
+												tag_creator.len - 1);
+					tag_id = swid_tag_id_create(tag_creator, unique_sw_id,
+												chunk_empty);
+					entry_size = 2 + tag_creator.len + 2 + unique_sw_id.len;
+
+					/* Have we reached the maximum attribute size? */
+					if (attr_size + entry_size > max_attr_size)
+					{
+						out_msg->add_attribute(out_msg, attr);
+						attr_size = PA_TNC_ATTR_HEADER_SIZE + 
+									TCG_SWID_REQ_MIN_SIZE;			
+						attr = tcg_swid_attr_req_create(
+									TCG_SWID_ATTR_REQ_FLAG_NONE,
+									swid_state->get_request_id(swid_state), 0);
+					}
+					cast_attr = (tcg_swid_attr_req_t*)attr;
+					cast_attr->add_target(cast_attr, tag_id);
+				}
+				json_object_put(jresponse);
+
+				out_msg->add_attribute(out_msg, attr);
+				break;
+			case FAILED:
+			default:
+				break;
+		}
+
+		if (status == FAILED)
+		{
+			enumerator = session->create_workitem_enumerator(session);
+			while (enumerator->enumerate(enumerator, &workitem))
+			{
+				if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
+				{
+					session->remove_workitem(session, enumerator);
+					eval = TNC_IMV_EVALUATION_RESULT_ERROR;
+					rec = workitem->set_result(workitem, error_str, eval);
+					state->update_recommendation(state, rec, eval);
+					imcv_db->finalize_workitem(imcv_db, workitem);
+					workitem->destroy(workitem);
+					break;
+				}
+			}
+			enumerator->destroy(enumerator);
+		}
+	}
+
 	/* finalized all workitems ? */
 	if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
 		session->get_workitem_count(session, imv_id) == 0)
@@ -471,6 +665,7 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
 METHOD(imv_agent_if_t, destroy, void,
 	private_imv_swid_agent_t *this)
 {
+	DESTROY_IF(this->rest_api);
 	this->agent->destroy(this->agent);
 	free(this);
 	libpts_deinit();
@@ -484,6 +679,8 @@ imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
 {
 	private_imv_swid_agent_t *this;
 	imv_agent_t *agent;
+	char *rest_api_uri;
+	u_int rest_api_timeout;
 
 	agent = imv_agent_create(name, msg_types, countof(msg_types), id,
 							 actual_version);
@@ -505,6 +702,14 @@ imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
 		.agent = agent,
 	);
 
+	rest_api_uri = lib->settings->get_str(lib->settings,
+						"%s.plugins.imv-swid.rest_api_uri", NULL, lib->ns);
+	rest_api_timeout = lib->settings->get_int(lib->settings,
+						"%s.plugins.imv-swid.rest_api_timeout", 120, lib->ns);
+	if (rest_api_uri)
+	{
+		this->rest_api = imv_swid_rest_create(rest_api_uri, rest_api_timeout);
+	}
 	libpts_init();
 
 	return &this->public;
diff --git a/src/libpts/plugins/imv_swid/imv_swid_rest.c b/src/libpts/plugins/imv_swid/imv_swid_rest.c
new file mode 100644
index 0000000..143b0b2
--- /dev/null
+++ b/src/libpts/plugins/imv_swid/imv_swid_rest.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "imv_swid_rest.h"
+
+typedef struct private_imv_swid_rest_t private_imv_swid_rest_t;
+
+/**
+ * Private data of an imv_swid_rest_t object.
+ */
+struct private_imv_swid_rest_t {
+
+	/**
+	 * Public members of imv_swid_rest_t
+	 */
+	imv_swid_rest_t public;
+
+	/**
+	 * URI of REST API
+	 */
+	char *uri;
+
+	/**
+	 * Timeout of REST API connection
+	 */
+	u_int timeout;
+
+};
+
+#define HTTP_STATUS_CODE_PRECONDITION_FAILED	412
+
+METHOD(imv_swid_rest_t, post, status_t,
+	private_imv_swid_rest_t *this, char *command, json_object *jrequest,
+	json_object **jresponse)
+{
+	struct json_tokener *tokener;
+	chunk_t data, response = chunk_empty;
+	status_t status;
+	char *uri;
+	int code;
+
+	if (asprintf(&uri, "%s%s",this->uri, command) < 0)
+	{
+		return FAILED;
+	}
+	data = chunk_from_str((char*)json_object_to_json_string(jrequest));
+
+	status = lib->fetcher->fetch(lib->fetcher, uri, &response,
+				FETCH_TIMEOUT, this->timeout,
+				FETCH_REQUEST_DATA, data,
+				FETCH_REQUEST_TYPE, "application/json; charset=utf-8",
+				FETCH_REQUEST_HEADER, "Accept: application/json",
+				FETCH_REQUEST_HEADER, "Expect:",
+				FETCH_RESPONSE_CODE, &code,
+				FETCH_END);
+	free(uri);
+
+	if (status == SUCCESS)
+	{
+		return 	SUCCESS;
+	}
+
+	if (code != HTTP_STATUS_CODE_PRECONDITION_FAILED || !response.ptr)
+	{
+		DBG2(DBG_IMV, "REST http request failed with status code: %d", code);
+		return FAILED;
+	}
+
+	if (jresponse)
+	{
+		/* Parse HTTP response into a JSON object */
+		tokener = json_tokener_new();
+		*jresponse = json_tokener_parse_ex(tokener, response.ptr, response.len);
+		json_tokener_free(tokener);
+	}
+	free(response.ptr);
+
+	return NEED_MORE;
+}
+
+METHOD(imv_swid_rest_t, destroy, void,
+	private_imv_swid_rest_t *this)
+{
+	free(this->uri);
+	free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_swid_rest_t *imv_swid_rest_create(char *uri, u_int timeout)
+{
+	private_imv_swid_rest_t *this;
+
+	INIT(this,
+		.public = {
+			.post = _post,
+			.destroy = _destroy,
+		},
+		.uri = strdup(uri),
+		.timeout = timeout,
+	);
+
+	return &this->public;
+}
+
+
diff --git a/src/libpts/plugins/imv_swid/imv_swid_rest.h b/src/libpts/plugins/imv_swid/imv_swid_rest.h
new file mode 100644
index 0000000..93e3d6a
--- /dev/null
+++ b/src/libpts/plugins/imv_swid/imv_swid_rest.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013-2014 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 imv_swid imv_swid
+ * @ingroup libimcv_plugins
+ *
+ * @defgroup imv_swid_rest_t imv_swid_rest
+ * @{ @ingroup imv_swid
+ */
+
+#ifndef IMV_SWID_REST_H_
+#define IMV_SWID_REST_H_
+
+#include <library.h>
+
+#include <json/json.h>
+
+typedef struct imv_swid_rest_t imv_swid_rest_t;
+
+/**
+ * Public REST interface
+ */
+struct imv_swid_rest_t {
+
+	/**
+	 * Post a HTTP request including a JSON object
+	 *
+	 * @param jreq		JSON object in HTTP request
+	 * @param jresp		JSON object in HTTP response if NEED_MORE
+	 * @return			Status (SUCCESS, NEED_MORE or FAILED)
+	 */
+	status_t (*post)(imv_swid_rest_t *this, char *command, json_object *jreq,
+					 json_object **jresp);
+
+	/**
+	 * Destroy imv_swid_rest_t object
+	 */
+	void (*destroy)(imv_swid_rest_t *this);
+
+};
+
+/**
+ * Create an imv_swid_rest_t instance
+ *
+ * @param uri			REST URI (http://username:password@hostname[:port]/api/)
+ * @param timeout		Timeout of the REST connection
+ */
+imv_swid_rest_t* imv_swid_rest_create(char *uri, u_int timeout);
+
+#endif /** IMV_SWID_REST_H_ @}*/
diff --git a/src/libpts/plugins/imv_swid/imv_swid_state.c b/src/libpts/plugins/imv_swid/imv_swid_state.c
index 5be8c02..c68b57e 100644
--- a/src/libpts/plugins/imv_swid/imv_swid_state.c
+++ b/src/libpts/plugins/imv_swid/imv_swid_state.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -14,9 +14,11 @@
  */
 
 #include "imv_swid_state.h"
-#include "imv/imv_lang_string.h"
-#include "imv/imv_reason_string.h"
-#include "imv/imv_remediation_string.h"
+
+#include <imv/imv_lang_string.h>
+#include <imv/imv_reason_string.h>
+#include <imv/imv_remediation_string.h>
+#include <swid/swid_tag_id.h>
 
 #include <tncif_policy.h>
 
@@ -58,22 +60,12 @@ struct private_imv_swid_state_t {
 	/**
 	 * Maximum PA-TNC message size for this TNCCS connection
 	 */
-	u_int32_t max_msg_len;
+	uint32_t max_msg_len;
 
 	/**
 	 * Flags set for completed actions
 	 */
-	u_int32_t action_flags;
-
-	/**
-	 * Access Requestor ID Type
-	 */
-	u_int32_t ar_id_type;
-
-	/**
-	 * Access Requestor ID Value
-	 */
-	chunk_t ar_id_value;
+	uint32_t action_flags;
 
 	/**
 	 * IMV database session associatied with TNCCS connection
@@ -105,6 +97,36 @@ struct private_imv_swid_state_t {
 	 */
 	imv_remediation_string_t *remediation_string;
 
+	/**
+	 * SWID Tag Request ID
+	 */
+	uint32_t request_id;
+
+	/**
+	 * Number of processed SWID Tag IDs
+	 */
+	int tag_id_count;
+
+	/**
+	 * Number of processed SWID Tags
+	 */
+	int tag_count;
+
+	/**
+	 * Top level JSON object
+	 */
+	json_object *jobj;
+
+	/**
+	 * JSON array containing an inventory of SWID Tag IDs
+	 */
+	json_object *jarray;
+
+	/**
+	 * Angel count
+	 */
+	int angel_count;
+
 };
 
 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
@@ -133,46 +155,29 @@ METHOD(imv_state_t, set_flags, void,
 }
 
 METHOD(imv_state_t, set_max_msg_len, void,
-	private_imv_swid_state_t *this, u_int32_t max_msg_len)
+	private_imv_swid_state_t *this, uint32_t max_msg_len)
 {
 	this->max_msg_len = max_msg_len;
 }
 
-METHOD(imv_state_t, get_max_msg_len, u_int32_t,
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
 	private_imv_swid_state_t *this)
 {
 	return this->max_msg_len;
 }
 
 METHOD(imv_state_t, set_action_flags, void,
-	private_imv_swid_state_t *this, u_int32_t flags)
+	private_imv_swid_state_t *this, uint32_t flags)
 {
 	this->action_flags |= flags;
 }
 
-METHOD(imv_state_t, get_action_flags, u_int32_t,
+METHOD(imv_state_t, get_action_flags, uint32_t,
 	private_imv_swid_state_t *this)
 {
 	return this->action_flags;
 }
 
-METHOD(imv_state_t, set_ar_id, void,
-	private_imv_swid_state_t *this, u_int32_t id_type, chunk_t id_value)
-{
-	this->ar_id_type = id_type;
-	this->ar_id_value = chunk_clone(id_value);
-}
-
-METHOD(imv_state_t, get_ar_id, chunk_t,
-	private_imv_swid_state_t *this, u_int32_t *id_type)
-{
-	if (id_type)
-	{
-		*id_type = this->ar_id_type;
-	}
-	return this->ar_id_value;
-}
-
 METHOD(imv_state_t, set_session, void,
 	private_imv_swid_state_t *this, imv_session_t *session)
 {
@@ -232,10 +237,10 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
 METHOD(imv_state_t, destroy, void,
 	private_imv_swid_state_t *this)
 {
+	json_object_put(this->jobj);
 	DESTROY_IF(this->session);
 	DESTROY_IF(this->reason_string);
 	DESTROY_IF(this->remediation_string);
-	free(this->ar_id_value.ptr);
 	free(this);
 }
 
@@ -251,6 +256,83 @@ METHOD(imv_swid_state_t, get_handshake_state, imv_swid_handshake_state_t,
 	return this->handshake_state;
 }
 
+METHOD(imv_swid_state_t, set_request_id, void,
+	private_imv_swid_state_t *this, uint32_t request_id)
+{
+	this->request_id = request_id;
+}
+
+METHOD(imv_swid_state_t, get_request_id, uint32_t,
+	private_imv_swid_state_t *this)
+{
+	return this->request_id;
+}
+
+METHOD(imv_swid_state_t, set_swid_inventory, void,
+    private_imv_swid_state_t *this, swid_inventory_t *inventory)
+{
+	chunk_t tag_creator, unique_sw_id;
+	char software_id[256];
+	json_object *jstring;
+	swid_tag_id_t *tag_id;
+	enumerator_t *enumerator;
+
+	enumerator = inventory->create_enumerator(inventory);
+	while (enumerator->enumerate(enumerator, &tag_id))
+	{
+		/* Construct software ID from tag creator and unique software ID */
+		tag_creator = tag_id->get_tag_creator(tag_id);
+		unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+		snprintf(software_id, 256, "%.*s_%.*s",
+				 tag_creator.len, tag_creator.ptr,
+				 unique_sw_id.len, unique_sw_id.ptr);
+		DBG3(DBG_IMV, "  %s", software_id);
+
+		/* Add software ID to JSON array */
+		jstring = json_object_new_string(software_id);
+		json_object_array_add(this->jarray, jstring);
+	}
+	enumerator->destroy(enumerator);
+}
+
+METHOD(imv_swid_state_t, get_swid_inventory, json_object*,
+	private_imv_swid_state_t *this)
+{
+	return this->jobj;
+}
+
+METHOD(imv_swid_state_t, set_count, void,
+	private_imv_swid_state_t *this, int tag_id_count, int tag_count)
+{
+	this->tag_id_count += tag_id_count;
+	this->tag_count += tag_count;
+}
+
+METHOD(imv_swid_state_t, get_count, void,
+	private_imv_swid_state_t *this, int *tag_id_count, int *tag_count)
+{
+	if (tag_id_count)
+	{
+		*tag_id_count = this->tag_id_count;
+	}
+	if (tag_count)
+	{
+		*tag_count = this->tag_count;
+	}
+}
+
+METHOD(imv_swid_state_t, set_angel_count, void,
+	private_imv_swid_state_t *this, bool start)
+{
+	this->angel_count += start ? 1 : -1;
+}
+
+METHOD(imv_swid_state_t, get_angel_count, int,
+	private_imv_swid_state_t *this)
+{
+	return this->angel_count;
+}
+
 /**
  * Described in header.
  */
@@ -269,8 +351,6 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
 				.get_max_msg_len = _get_max_msg_len,
 				.set_action_flags = _set_action_flags,
 				.get_action_flags = _get_action_flags,
-				.set_ar_id = _set_ar_id,
-				.get_ar_id = _get_ar_id,
 				.set_session = _set_session,
 				.get_session= _get_session,
 				.change_state = _change_state,
@@ -283,13 +363,25 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
 			},
 			.set_handshake_state = _set_handshake_state,
 			.get_handshake_state = _get_handshake_state,
+			.set_request_id = _set_request_id,
+			.get_request_id = _get_request_id,
+			.set_swid_inventory = _set_swid_inventory,
+			.get_swid_inventory = _get_swid_inventory,
+			.set_count = _set_count,
+			.get_count = _get_count,
+			.set_angel_count = _set_angel_count,
+			.get_angel_count = _get_angel_count,
 		},
 		.state = TNC_CONNECTION_STATE_CREATE,
 		.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
 		.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
 		.connection_id = connection_id,
+		.jobj = json_object_new_object(),
+		.jarray = json_object_new_array(),
 	);
 
+	json_object_object_add(this->jobj, "data", this->jarray);
+
 	return &this->public.interface;
 }
 
diff --git a/src/libpts/plugins/imv_swid/imv_swid_state.h b/src/libpts/plugins/imv_swid/imv_swid_state.h
index d6e5840..7ffabfd 100644
--- a/src/libpts/plugins/imv_swid/imv_swid_state.h
+++ b/src/libpts/plugins/imv_swid/imv_swid_state.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -25,8 +25,11 @@
 #define IMV_SWID_STATE_H_
 
 #include <imv/imv_state.h>
+#include <swid/swid_inventory.h>
 #include <library.h>
 
+#include <json/json.h>
+
 typedef struct imv_swid_state_t imv_swid_state_t;
 typedef enum imv_swid_handshake_state_t imv_swid_handshake_state_t;
 
@@ -64,6 +67,64 @@ struct imv_swid_state_t {
 	 */
 	imv_swid_handshake_state_t (*get_handshake_state)(imv_swid_state_t *this);
 
+	/**
+	 * Set the SWID request ID
+	 *
+	 * @param request_id		SWID request ID to be set
+	 */
+	void (*set_request_id)(imv_swid_state_t *this, uint32_t request_id);
+
+	/**
+	 * Get the SWID request ID
+	 *
+	 * @return					SWID request ID
+	 */
+	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);
+
+   /**
+     * 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 [or with multiple attributes increment] SWID Tag [ID] counters
+	 *
+	 * @param tag_id_count		Number of received SWID Tag IDs
+	 * @param tag_count			Number of received SWID Tags
+	 */
+	void (*set_count)(imv_swid_state_t *this, int tag_id_count, int tag_count);
+
+	/**
+	 * Set [or with multiple attributes increment] SWID Tag [ID] counters
+	 *
+	 * @param tag_id_count		Number of received SWID Tag IDs
+	 * @param tag_count			Number of received SWID Tags
+	 */
+	void (*get_count)(imv_swid_state_t *this, int *tag_id_count, int *tag_count);
+
+	/**
+	 * Increase/Decrease the ITA Angel count
+	 *
+	 * @param start				TRUE increases and FALSE decreases count by one
+	 */
+	void (*set_angel_count)(imv_swid_state_t *this, bool start);
+
+	/**
+	 * Get the ITA Angel count
+	 *
+	 * @return					ITA Angel count
+	 */
+	int (*get_angel_count)(imv_swid_state_t *this);
+
 };
 
 /**
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c
index c6b4131..be8aa40 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.c
+++ b/src/libpts/pts/components/ita/ita_comp_ima.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -18,27 +18,20 @@
 
 #include "libpts.h"
 #include "pts/pts_pcr.h"
+#include "pts/pts_ima_bios_list.h"
+#include "pts/pts_ima_event_list.h"
 #include "pts/components/pts_component.h"
 
 #include <utils/debug.h>
+#include <crypto/hashers/hasher.h>
 #include <pen/pen.h>
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-
 #define SECURITY_DIR				"/sys/kernel/security/"
 #define IMA_BIOS_MEASUREMENTS		SECURITY_DIR "tpm0/binary_bios_measurements"
 #define IMA_RUNTIME_MEASUREMENTS	SECURITY_DIR "ima/binary_runtime_measurements"
-#define IMA_PCR						10
-#define IMA_TYPE_LEN				3
-#define IMA_FILENAME_LEN_MAX	255
+#define IMA_FILENAME_LEN_MAX		255
 
 typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
-typedef struct bios_entry_t bios_entry_t;
-typedef struct ima_entry_t ima_entry_t;
 typedef enum ima_state_t ima_state_t;
 
 enum ima_state_t {
@@ -66,14 +59,9 @@ struct pts_ita_comp_ima_t {
 	pts_comp_func_name_t *name;
 
 	/**
-	 * AIK keyid
-	 */
-	chunk_t keyid;
-
-	/**
 	 * Sub-component depth
 	 */
-	u_int32_t depth;
+	uint32_t depth;
 
 	/**
 	 * PTS measurement database
@@ -83,7 +71,7 @@ struct pts_ita_comp_ima_t {
 	/**
 	 * Primary key for AIK database entry
 	 */
-	int kid;
+	int aik_id;
 
 	/**
 	 * Primary key for IMA BIOS Component Functional Name database entry
@@ -118,12 +106,12 @@ struct pts_ita_comp_ima_t {
 	/**
      * IMA BIOS measurements
 	 */
-	linked_list_t *bios_list;
+	pts_ima_bios_list_t *bios_list;
 
 	/**
      * IMA runtime file measurements
 	 */
-	linked_list_t *ima_list;
+	pts_ima_event_list_t *ima_list;
 
 	/**
 	 * Whether to send pcr_before and pcr_after info
@@ -131,9 +119,9 @@ struct pts_ita_comp_ima_t {
 	bool pcr_info;
 
 	/**
-	 * IMA measurement time
+	 * Creation time of measurement
 	 */
-	time_t measurement_time;
+	time_t creation_time;
 
 	/**
 	 * IMA state machine
@@ -173,222 +161,11 @@ struct pts_ita_comp_ima_t {
 };
 
 /**
- * Linux IMA BIOS measurement entry
- */
-struct bios_entry_t {
-
-	/**
-	 * PCR register
-	 */
-	u_int32_t pcr;
-
-	/**
-	 * SHA1 measurement hash
-	 */
-	chunk_t measurement;
-};
-
-/**
- * Linux IMA runtime file measurement entry
- */
-struct ima_entry_t {
-
-	/**
-	 * SHA1 measurement hash
-	 */
-	chunk_t measurement;
-
-	/**
-	 * absolute path of executable files or basename of dynamic libraries
-	 */
-	char *filename;
-};
-
-/**
- * Free a bios_entry_t object
- */
-static void free_bios_entry(bios_entry_t *this)
-{
-	free(this->measurement.ptr);
-	free(this);
-}
-
-/**
- * Free an ima_entry_t object
- */
-static void free_ima_entry(ima_entry_t *this)
-{
-	free(this->measurement.ptr);
-	free(this->filename);
-	free(this);
-}
-
-/**
- * Load a PCR measurement file and determine the creation date
- */
-static bool load_bios_measurements(char *file, linked_list_t *list,
-								   time_t *created)
-{
-	u_int32_t pcr, num, len;
-	bios_entry_t *entry;
-	struct stat st;
-	ssize_t res;
-	int fd;
-
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-	{
-		DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
-		return FALSE;
-	}
-
-	if (fstat(fd, &st) == -1)
-	{
-		DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
-			 strerror(errno));
-		close(fd);
-		return FALSE;
-	}
-	*created = st.st_ctime;
-
-	while (TRUE)
-	{
-		res = read(fd, &pcr, 4);
-		if (res == 0)
-		{
-			DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
-				 file, list->get_count(list));
-			close(fd);
-			return TRUE;
-		}
-
-		entry = malloc_thing(bios_entry_t);
-		entry->pcr = pcr;
-		entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
-
-		if (res != 4)
-		{
-			break;
-		}
-		if (read(fd, &num, 4) != 4)
-		{
-			break;
-		}
-		if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
-		{
-			break;
-		}
-		if (read(fd, &len, 4) != 4)
-		{
-			break;
-		}
-		if (lseek(fd, len, SEEK_CUR) == -1)
-		{
-			break;
-		}
-		list->insert_last(list, entry);
-	}
-
-	DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
-		 strerror(errno));
-	free_bios_entry(entry);
-	close(fd);
-	return FALSE;
-}
-
-/**
- * Load an IMA runtime measurement file and determine the creation and
- * update dates
- */
-static bool load_runtime_measurements(char *file, linked_list_t *list,
-									 time_t *created)
-{
-	u_int32_t pcr, len;
-	ima_entry_t *entry;
-	char type[IMA_TYPE_LEN];
-	struct stat st;
-	ssize_t res;
-	int fd;
-
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-	{
-		DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
-		return TRUE;
-	}
-
-	if (fstat(fd, &st) == -1)
-	{
-		DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
-			 strerror(errno));
-		close(fd);
-		return FALSE;
-	}
-	*created = st.st_ctime;
-
-	while (TRUE)
-	{
-		res = read(fd, &pcr, 4);
-		if (res == 0)
-		{
-			DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)",
-				 file, list->get_count(list));
-			close(fd);
-			return TRUE;
-		}
-
-		entry = malloc_thing(ima_entry_t);
-		entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
-		entry->filename = NULL;
-
-		if (res != 4 || pcr != IMA_PCR)
-		{
-			break;
-		}
-		if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
-		{
-			break;
-		}
-		if (read(fd, &len, 4) != 4 || len != IMA_TYPE_LEN)
-		{
-			break;
-		}
-		if (read(fd, type, IMA_TYPE_LEN) != IMA_TYPE_LEN ||
-			memcmp(type, "ima", IMA_TYPE_LEN))
-		{
-			break;
-		}
-		if (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1)
-		{
-			break;
-		}
-		if (read(fd, &len, 4) != 4)
-		{
-			break;
-		}
-		entry->filename = malloc(len + 1);
-		if (read(fd, entry->filename, len) != len)
-		{
-			break;
-		}
-		entry->filename[len] = '\0';
-
-		list->insert_last(list, entry);
-	}
-
-	DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s",
-		 file, strerror(errno));
-	free_ima_entry(entry);
-	close(fd);
-	return FALSE;
-}
-
-/**
- * Extend measurement into PCR an create evidence
+ * Extend measurement into PCR and create evidence
  */
 static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
-									   u_int8_t qualifier, pts_pcr_t *pcrs,
-									   u_int32_t pcr, chunk_t measurement)
+									   uint8_t qualifier, pts_pcr_t *pcrs,
+									   uint32_t pcr, chunk_t measurement)
 {
 	size_t pcr_len;
 	pts_pcr_transform_t pcr_transform;
@@ -414,7 +191,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
 	name = this->name->clone(this->name);
 	name->set_qualifier(name, qualifier);
 	evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
-			 		pcr_transform, this->measurement_time, measurement);
+						pcr_transform, this->creation_time, measurement);
 	if (this->pcr_info)
 	{
 		pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
@@ -424,15 +201,83 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
 }
 
 /**
+ * Generate an IMA or IMA-NG hash from an event digest and event name
+ *
+ * @param digest		event digest
+ * @param ima_algo		hash algorithm string ("sha1:", "sha256:", etc.)
+ * @param ima_name		event name
+ * @param little_endian	endianness of client platform
+ * @param algo			hash algorithm used by TPM
+ * @param hash_buf		hash value to be compared with TPM measurement
+ */
+static bool ima_hash(chunk_t digest, char *ima_algo, char *ima_name,
+					 bool little_endian, pts_meas_algorithms_t algo,
+					 char *hash_buf)
+{
+	hash_algorithm_t hash_alg;
+	hasher_t *hasher;
+	bool success;
+
+	hash_alg = pts_meas_algo_to_hash(algo);
+	hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
+	if (!hasher)
+	{
+		DBG1(DBG_PTS, "%N hasher could not be created",
+			 hash_algorithm_short_names, hash_alg);
+		return FALSE;
+	}
+
+	if (ima_algo)
+	{
+		uint32_t d_len, n_len;
+		chunk_t algo_name, event_name, digest_len, name_len;
+
+		/* IMA-NG hash */
+		algo_name  = chunk_create(ima_algo, strlen(ima_algo) + 1);
+		event_name = chunk_create(ima_name, strlen(ima_name) + 1);
+
+		d_len = algo_name.len + digest.len;
+		digest_len = chunk_create((uint8_t*)&d_len, sizeof(d_len));
+		/* TODO handle endianness of both client and server platforms */
+
+		n_len = event_name.len;
+		name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len));
+		/* TODO handle endianness of both client and server platforms */
+
+		success = hasher->get_hash(hasher, digest_len, NULL) &&
+				  hasher->get_hash(hasher, algo_name, NULL) &&
+				  hasher->get_hash(hasher, digest, NULL) &&
+				  hasher->get_hash(hasher, name_len, NULL) &&
+				  hasher->get_hash(hasher, event_name, hash_buf);
+	}
+	else
+	{
+		u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
+		chunk_t file_name;
+
+		/* IMA legacy hash */
+		memset(filename_buffer, 0, sizeof(filename_buffer));
+		strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX);
+		file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
+
+		success = hasher->get_hash(hasher, digest, NULL) &&
+				  hasher->get_hash(hasher, file_name, hash_buf);
+	}
+	hasher->destroy(hasher);
+
+	return success;
+}
+
+/**
  * Compute and check boot aggregate value by hashing PCR0 to PCR7
  */
-static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
+static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
+								 char *algo)
 {
-	u_int32_t i;
-	u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
 	u_char pcr_buffer[HASH_SIZE_SHA1];
-	chunk_t file_name, boot_aggregate;
+	chunk_t boot_aggregate;
 	hasher_t *hasher;
+	uint32_t i;
 	bool success, pcr_ok = TRUE;
 
 	hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
@@ -448,19 +293,20 @@ static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
 	}
 	if (pcr_ok)
 	{
-		boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
-		memset(filename_buffer, 0, sizeof(filename_buffer));
-		strcpy(filename_buffer, "boot_aggregate");
-		file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
-
-		pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer) &&
-				 hasher->get_hash(hasher, boot_aggregate, NULL) &&
-				 hasher->get_hash(hasher, file_name, boot_aggregate.ptr);
+		pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer);
 	}
 	hasher->destroy(hasher);
 
 	if (pcr_ok)
 	{
+		boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
+
+		/* TODO handle endianness of client platform */
+		pcr_ok = ima_hash(boot_aggregate, algo, "boot_aggregate",
+						  TRUE, PTS_MEAS_ALGO_SHA1, pcr_buffer);
+	}
+	if (pcr_ok)
+	{
 		success = chunk_equals(boot_aggregate, measurement);
 		DBG1(DBG_PTS, "boot aggregate value is %scorrect",
 					   success ? "":"in");
@@ -479,26 +325,28 @@ METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
 	return this->name;
 }
 
-METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+METHOD(pts_component_t, get_evidence_flags, uint8_t,
 	pts_ita_comp_ima_t *this)
 {
 	return PTS_REQ_FUNC_COMP_EVID_PCR;
 }
 
-METHOD(pts_component_t, get_depth, u_int32_t,
+METHOD(pts_component_t, get_depth, uint32_t,
 	pts_ita_comp_ima_t *this)
 {
 	return this->depth;
 }
 
 METHOD(pts_component_t, measure, status_t,
-	pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
+	pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
 	pts_comp_evidence_t **evidence)
 {
-	bios_entry_t *bios_entry;
-	ima_entry_t *ima_entry;
 	pts_pcr_t *pcrs;
 	pts_comp_evidence_t *evid = NULL;
+	size_t algo_len, name_len;
+	chunk_t measurement;
+	char *uri, *algo, *name;
+	uint32_t pcr;
 	status_t status;
 
 	pcrs = pts->get_pcrs(pts);
@@ -509,25 +357,25 @@ METHOD(pts_component_t, measure, status_t,
 		switch (this->state)
 		{
 			case IMA_STATE_INIT:
-				if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS,
-					this->bios_list, &this->measurement_time))
+				this->bios_list = pts_ima_bios_list_create(
+												IMA_BIOS_MEASUREMENTS);
+				if (!this->bios_list)
 				{
 					return FAILED;
 				}
+				this->creation_time = this->bios_list->get_time(this->bios_list);
 				this->bios_count = this->bios_list->get_count(this->bios_list);
 				this->state = IMA_STATE_BIOS;
 				/* fall through to next state */
 			case IMA_STATE_BIOS:
-				status = this->bios_list->remove_first(this->bios_list,
-													  (void**)&bios_entry);
+				status = this->bios_list->get_next(this->bios_list, &pcr,
+											       &measurement);
 				if (status != SUCCESS)
 				{
 					DBG1(DBG_PTS, "could not retrieve bios measurement entry");
 					return status;
 				}
-				evid = extend_pcr(this, qualifier, pcrs, bios_entry->pcr,
-								  bios_entry->measurement);
-				free(bios_entry);
+				evid = extend_pcr(this, qualifier, pcrs, pcr, measurement);
 
 				this->state = this->bios_list->get_count(this->bios_list) ?
 										IMA_STATE_BIOS : IMA_STATE_INIT;
@@ -542,17 +390,20 @@ METHOD(pts_component_t, measure, status_t,
 		switch (this->state)
 		{
 			case IMA_STATE_INIT:
-				if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS,
-								this->ima_list, &this->measurement_time))
+				this->ima_list = pts_ima_event_list_create(
+												IMA_RUNTIME_MEASUREMENTS);
+				if (!this->ima_list)
 				{
 					return FAILED;
 				}
+				this->creation_time = this->ima_list->get_time(this->ima_list);
+				this->count = this->ima_list->get_count(this->ima_list);
 				this->state = IMA_STATE_BOOT_AGGREGATE;
 				/* fall through to next state */
 			case IMA_STATE_BOOT_AGGREGATE:
 			case IMA_STATE_RUNTIME:
-				status = this->ima_list->remove_first(this->ima_list,
-													 (void**)&ima_entry);
+				status = this->ima_list->get_next(this->ima_list, &measurement,
+												  &algo, &name);
 				if (status != SUCCESS)
 				{
 					DBG1(DBG_PTS, "could not retrieve ima measurement entry");
@@ -560,20 +411,33 @@ METHOD(pts_component_t, measure, status_t,
 				}
 				if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
 				{
-					if (!check_boot_aggregate(pcrs, ima_entry->measurement))
+					if (!check_boot_aggregate(pcrs, measurement, algo))
 					{
 						return FAILED;
 					}
 				}
 				evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
-								  ima_entry->measurement);
+								  measurement);
 				if (evid)
 				{
+					if (algo)
+					{
+						algo_len = strlen(algo);
+						name_len = strlen(name);
+						uri = malloc(algo_len + name_len + 1);
+						memcpy(uri, algo, algo_len);
+						strcpy(uri + algo_len, name);
+					}
+					else
+					{
+						uri = strdup(name);
+					}
 					evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
-											   ima_entry->filename);
+											   uri);
+					free(uri);
 				}
-				free(ima_entry->filename);
-				free(ima_entry);
+				free(name);
+				free(algo);
 
 				this->state = this->ima_list->get_count(this->ima_list) ?
 									IMA_STATE_RUNTIME : IMA_STATE_END;
@@ -598,40 +462,80 @@ METHOD(pts_component_t, measure, status_t,
 			SUCCESS : NEED_MORE;
 }
 
-METHOD(pts_component_t, verify, status_t,
-	pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
-	pts_comp_evidence_t *evidence)
+/**
+ * Parse a validation URI of the form <hash algorithm>:<event name>
+ * into its components
+ */
+static pts_meas_algorithms_t parse_validation_uri(pts_comp_evidence_t *evidence,
+								char **ima_name, char **ima_algo, char *algo_buf)
 {
-	bool has_pcr_info;
-	u_int32_t pcr, vid, name;
-	enum_name_t *names;
-	pts_meas_algorithms_t algo;
-	pts_pcr_transform_t transform;
-	pts_pcr_t *pcrs;
-	time_t measurement_time;
-	chunk_t measurement, pcr_before, pcr_after;
-	status_t status;
-	char *uri;
+    pts_meas_algorithms_t hash_algo;
+	char *uri, *pos, *algo, *name;
 
-	/* some first time initializations */
-	if (!this->keyid.ptr)
+	evidence->get_validation(evidence, &uri);
+
+	/* IMA-NG format? */
+	pos = strchr(uri, ':');
+	if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX)
 	{
-		if (!pts->get_aik_keyid(pts, &this->keyid))
+		memset(algo_buf, '\0', IMA_ALGO_LEN_MAX);
+		memcpy(algo_buf, uri, pos - uri + 1);
+		algo = algo_buf;
+		name = pos + 1;
+
+		if (streq(algo, "sha1:") || streq(algo, ":"))
+		{
+			hash_algo = PTS_MEAS_ALGO_SHA1;
+		}
+		else if (streq(algo, "sha256:"))
 		{
-			DBG1(DBG_PTS, "AIK keyid not available");
-			return FAILED;
+			hash_algo = PTS_MEAS_ALGO_SHA256;
 		}
-		this->keyid = chunk_clone(this->keyid);
-		if (!this->pts_db)
+		else if (streq(algo, "sha384:"))
 		{
-			DBG1(DBG_PTS, "pts database not available");
-			return FAILED;
+			hash_algo = PTS_MEAS_ALGO_SHA384;
+		}
+		else
+		{
+			hash_algo = PTS_MEAS_ALGO_NONE;
 		}
 	}
+	else
+	{
+		algo = NULL;
+		name = uri;
+		hash_algo = PTS_MEAS_ALGO_SHA1;
+	}
+
+	if (ima_name)
+	{
+		*ima_name = name;
+	}
+	if (ima_algo)
+	{
+		*ima_algo = algo;
+	}
+
+	return hash_algo;
+}
+
+METHOD(pts_component_t, verify, status_t,
+	pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
+	pts_comp_evidence_t *evidence)
+{
+	bool has_pcr_info;
+	uint32_t pcr;
+	pts_meas_algorithms_t algo;
+	pts_pcr_transform_t transform;
+	pts_pcr_t *pcrs;
+	time_t creation_time;
+	chunk_t measurement, pcr_before, pcr_after;
+	status_t status = NOT_FOUND;
 
+	this->aik_id = pts->get_aik_id(pts);
 	pcrs = pts->get_pcrs(pts);
 	measurement = evidence->get_measurement(evidence, &pcr,	&algo, &transform,
-											&measurement_time);
+											&creation_time);
 
 	if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
 					  PTS_ITA_QUALIFIER_TYPE_TRUSTED))
@@ -641,26 +545,22 @@ METHOD(pts_component_t, verify, status_t,
 			case IMA_STATE_INIT:
 				this->name->set_qualifier(this->name, qualifier);
 				status = this->pts_db->get_comp_measurement_count(this->pts_db,
-								this->name, this->keyid, algo, &this->bios_cid,
-								&this->kid, &this->bios_count);
+											this->name, this->aik_id, algo,
+											&this->bios_cid, &this->bios_count);
 				this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
 				if (status != SUCCESS)
 				{
 					return status;
 				}
-				vid = this->name->get_vendor_id(this->name);
-				name = this->name->get_name(this->name);
-				names = pts_components->get_comp_func_names(pts_components, vid);
 
 				if (this->bios_count)
 				{
-					DBG1(DBG_PTS, "checking %d %N '%N' BIOS evidence measurements",
-								   this->bios_count, pen_names, vid, names, name);
+					DBG1(DBG_PTS, "checking %d BIOS evidence measurements",
+								   this->bios_count);
 				}
 				else
 				{
-					DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements",
-								   pen_names, vid, names, name);
+					DBG1(DBG_PTS, "registering BIOS evidence measurements");
 					this->is_bios_registering = TRUE;
 				}
 
@@ -670,8 +570,8 @@ METHOD(pts_component_t, verify, status_t,
 				if (this->is_bios_registering)
 				{
 					status = this->pts_db->insert_comp_measurement(this->pts_db,
-										measurement, this->bios_cid, this->kid,
-										++this->seq_no,	pcr, algo);
+									measurement, this->bios_cid, this->aik_id,
+									++this->seq_no,	pcr, algo);
 					if (status != SUCCESS)
 					{
 						return status;
@@ -681,8 +581,8 @@ METHOD(pts_component_t, verify, status_t,
 				else
 				{
 					status = this->pts_db->check_comp_measurement(this->pts_db,
-										measurement, this->bios_cid, this->kid,
-										++this->seq_no,	pcr, algo);
+									measurement, this->bios_cid, this->aik_id,
+									++this->seq_no,	pcr, algo);
 					if (status == FAILED)
 					{
 						return status;
@@ -697,13 +597,34 @@ METHOD(pts_component_t, verify, status_t,
 						   PTS_ITA_QUALIFIER_TYPE_OS))
 	{
 		int ima_count;
+		char *ima_algo, *ima_name;
+		char algo_buf[IMA_ALGO_LEN_MAX];
+		pts_meas_algorithms_t hash_algo;
+
+		hash_algo = parse_validation_uri(evidence, &ima_name, &ima_algo,
+										 algo_buf);
 
 		switch (this->state)
 		{
 			case IMA_STATE_BIOS:
-				if (!check_boot_aggregate(pcrs, measurement))
+				this->state = IMA_STATE_RUNTIME;
+
+				if (!streq(ima_name, "boot_aggregate"))
+				{
+					DBG1(DBG_PTS, "ima: name must be 'boot_aggregate' "
+								  "but is '%s'", ima_name);
+					return FAILED;
+				}
+				if (hash_algo != PTS_MEAS_ALGO_SHA1)
+				{
+					DBG1(DBG_PTS, "ima: boot_aggregate algorithm must be %N "
+								  "but is %N",
+								   pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1,
+								   pts_meas_algorithm_names, hash_algo);
+					return FAILED;
+				}
+				if (!check_boot_aggregate(pcrs, measurement, ima_algo))
 				{
-					this->state = IMA_STATE_RUNTIME;
 					return FAILED;
 				}
 				this->state = IMA_STATE_INIT;
@@ -711,33 +632,30 @@ METHOD(pts_component_t, verify, status_t,
 			case IMA_STATE_INIT:
 				this->name->set_qualifier(this->name, qualifier);
 				status = this->pts_db->get_comp_measurement_count(this->pts_db,
-										this->name, this->keyid, algo,
-										&this->ima_cid,	&this->kid, &ima_count);
+												this->name, this->aik_id, algo,
+												&this->ima_cid,	&ima_count);
 				this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
 				if (status != SUCCESS)
 				{
 					return status;
 				}
-				vid = this->name->get_vendor_id(this->name);
-				name = this->name->get_name(this->name);
-				names = pts_components->get_comp_func_names(pts_components, vid);
 
 				if (ima_count)
 				{
-					DBG1(DBG_PTS, "checking %N '%N' boot aggregate evidence "
-								  "measurement", pen_names, vid, names, name);
+					DBG1(DBG_PTS, "checking boot aggregate evidence "
+								  "measurement");
 					status = this->pts_db->check_comp_measurement(this->pts_db,
 													measurement, this->ima_cid,
-													this->kid, 1, pcr, algo);
+													this->aik_id, 1, pcr, algo);
 				}
 				else
 				{
-					DBG1(DBG_PTS, "registering %N '%N' boot aggregate evidence "
-								   "measurement", pen_names, vid, names, name);
+					DBG1(DBG_PTS, "registering boot aggregate evidence "
+								  "measurement");
 					this->is_ima_registering = TRUE;
 					status = this->pts_db->insert_comp_measurement(this->pts_db,
 													measurement, this->ima_cid,
-										 			this->kid, 1, pcr, algo);
+													this->aik_id, 1, pcr, algo);
 				}
 				this->state = IMA_STATE_RUNTIME;
 
@@ -747,42 +665,76 @@ METHOD(pts_component_t, verify, status_t,
 				}
 				break;
 			case IMA_STATE_RUNTIME:
+			{
+				uint8_t hash_buf[HASH_SIZE_SHA512];
+				chunk_t digest, hash;
+				enumerator_t *e;
+
 				this->count++;
-				if (evidence->get_validation(evidence, &uri) !=
+				if (evidence->get_validation(evidence, NULL) !=
 					PTS_COMP_EVID_VALIDATION_PASSED)
 				{
-					DBG1(DBG_PTS, "policy URI could no be retrieved");
+					DBG1(DBG_PTS, "evidence validation failed");
 					this->count_failed++;
 					return FAILED;
 				}
-				status = this->pts_db->check_file_measurement(this->pts_db,
-												pts->get_platform_info(pts),
-												PTS_MEAS_ALGO_SHA1_IMA,
-												measurement, uri);
+				hash = chunk_create(hash_buf, pts_meas_algo_hash_size(algo));
+
+				e = this->pts_db->create_file_meas_enumerator(this->pts_db,
+												pts->get_platform_id(pts),
+												hash_algo, ima_name);
+				if (e)
+				{
+					while (e->enumerate(e, &digest))
+					{
+						if (!ima_hash(digest, ima_algo, ima_name,
+									  FALSE, algo, hash_buf))
+						{
+							status = FAILED;
+							break;
+						}
+						if (chunk_equals(measurement, hash))
+						{
+							status = SUCCESS;
+							break;
+						}
+						else
+						{
+							status = VERIFY_ERROR;
+						}
+					}
+					e->destroy(e);
+				}
+				else
+				{
+					status = FAILED;
+				}
+
 				switch (status)
 				{
 					case SUCCESS:
 						DBG3(DBG_PTS, "%#B for '%s' is ok",
-									   &measurement, uri);
+									   &measurement, ima_name);
 						this->count_ok++;
 						break;
 					case NOT_FOUND:
 						DBG2(DBG_PTS, "%#B for '%s' not found",
-									   &measurement, uri);
+									   &measurement, ima_name);
 						this->count_unknown++;
 						break;
 					case VERIFY_ERROR:
 						DBG1(DBG_PTS, "%#B for '%s' differs",
-									   &measurement, uri);
+									   &measurement, ima_name);
 						this->count_differ++;
 						break;
 					case FAILED:
 					default:
 						DBG1(DBG_PTS, "%#B for '%s' failed",
-									   &measurement, uri);
+									   &measurement, ima_name);
 						this->count_failed++;
 				}
 				break;
+			}
 			default:
 				return FAILED;
 		}
@@ -818,16 +770,15 @@ METHOD(pts_component_t, verify, status_t,
 }
 
 METHOD(pts_component_t, finalize, bool,
-	pts_ita_comp_ima_t *this, u_int8_t qualifier)
+	pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result)
 {
-	u_int32_t vid, name;
-	enum_name_t *names;
+	char result_buf[BUF_LEN];
+	char *pos = result_buf;
+	size_t len = BUF_LEN;
+	int written;
 	bool success = TRUE;
 
 	this->name->set_qualifier(this->name, qualifier);
-	vid = this->name->get_vendor_id(this->name);
-	name = this->name->get_name(this->name);
-	names = pts_components->get_comp_func_names(pts_components, vid);
 
 	if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
 					  PTS_ITA_QUALIFIER_TYPE_TRUSTED))
@@ -838,16 +789,20 @@ METHOD(pts_component_t, finalize, bool,
 			/* close registration */
 			this->is_bios_registering = FALSE;
 
-			DBG1(DBG_PTS, "registered %d %N '%N' BIOS evidence measurements",
-						   this->seq_no, pen_names, vid, names, name);
+			snprintf(pos, len, "registered %d BIOS evidence measurements",
+					 this->seq_no);
 		}
 		else if (this->seq_no < this->bios_count)
 		{
-			DBG1(DBG_PTS, "%d of %d %N '%N' BIOS evidence measurements missing",
-						   this->bios_count - this->seq_no, this->bios_count,
-						   pen_names, vid, names, name);
+			snprintf(pos, len, "%d of %d BIOS evidence measurements missing",
+					 this->bios_count - this->seq_no, this->bios_count);
 			success = FALSE;
 		}
+		else
+		{
+			snprintf(pos, len, "%d BIOS evidence measurements are ok",
+					 this->bios_count);
+		}
 	}
 	else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
 						   PTS_ITA_QUALIFIER_TYPE_OS))
@@ -858,26 +813,34 @@ METHOD(pts_component_t, finalize, bool,
 			/* close registration */
 			this->is_ima_registering = FALSE;
 
-			DBG1(DBG_PTS, "registered %N '%N' boot aggregate evidence "
-						  "measurement", pen_names, vid, names, name);
+			written = snprintf(pos, len, "registered IMA boot aggregate "
+							   "evidence measurement; ");
+			pos += written;
+			len -= written;
 		}
 		if (this->count)
 		{
-			DBG1(DBG_PTS, "processed %d %N '%N' file evidence measurements: "
-						  "%d ok, %d unknown, %d differ, %d failed",
-						   this->count, pen_names, vid, names, name,
-						   this->count_ok, this->count_unknown,
-						   this->count_differ, this->count_failed);
-			success = !this->count_differ && !this->count_failed;
+			snprintf(pos, len, "processed %d IMA file evidence measurements: "
+					 "%d ok, %d unknown, %d differ, %d failed",
+					 this->count, this->count_ok, this->count_unknown,
+					 this->count_differ, this->count_failed);
+		}
+		else
+		{
+			snprintf(pos, len, "no IMA file evidence measurements");
+            success = FALSE;
 		}
 	}
 	else
 	{
-		DBG1(DBG_PTS, "unsupported functional component name qualifier");
+		snprintf(pos, len, "unsupported functional component name qualifier");
 		success = FALSE;
 	}
 	this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
 
+	DBG1(DBG_PTS, "%s", result_buf);
+	result->write_data(result, chunk_from_str(result_buf));
+
 	return success;
 }
 
@@ -892,35 +855,28 @@ METHOD(pts_component_t, destroy, void,
 	pts_ita_comp_ima_t *this)
 {
 	int count;
-	u_int32_t vid, name;
-	enum_name_t *names;
 
 	if (ref_put(&this->ref))
 	{
-		vid = this->name->get_vendor_id(this->name);
-		name = this->name->get_name(this->name);
-		names = pts_components->get_comp_func_names(pts_components, vid);
 
 		if (this->is_bios_registering)
 		{
 			count = this->pts_db->delete_comp_measurements(this->pts_db,
-													this->bios_cid, this->kid);
-			DBG1(DBG_PTS, "deleted %d registered %N '%N' BIOS evidence "
-						  "measurements", count, pen_names, vid, names, name);
+												this->bios_cid, this->aik_id);
+			DBG1(DBG_PTS, "deleted %d registered BIOS evidence measurements",
+						   count);
 		}
 		if (this->is_ima_registering)
 		{
 			count = this->pts_db->delete_comp_measurements(this->pts_db,
-													this->ima_cid, this->kid);
-			DBG1(DBG_PTS, "deleted registered %N '%N' boot aggregate evidence "
-						  "measurement", pen_names, vid, names, name);
+												this->ima_cid, this->aik_id);
+			DBG1(DBG_PTS, "deleted registered boot aggregate evidence "
+						  "measurement");
 		}
-		this->bios_list->destroy_function(this->bios_list,
-										 (void *)free_bios_entry);
-		this->ima_list->destroy_function(this->ima_list,
-										 (void *)free_ima_entry);
+		DESTROY_IF(this->bios_list);
+		DESTROY_IF(this->ima_list);
 		this->name->destroy(this->name);
-		free(this->keyid.ptr);
+		
 		free(this);
 	}
 }
@@ -928,7 +884,7 @@ METHOD(pts_component_t, destroy, void,
 /**
  * See header
  */
-pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
+pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
 										 pts_database_t *pts_db)
 {
 	pts_ita_comp_ima_t *this;
@@ -948,10 +904,8 @@ pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
 										  PTS_QUALIFIER_UNKNOWN),
 		.depth = depth,
 		.pts_db = pts_db,
-		.bios_list = linked_list_create(),
-		.ima_list = linked_list_create(),
 		.pcr_info = lib->settings->get_bool(lib->settings,
-						"%s.plugins.imc-attestation.pcr_info", TRUE, lib->ns),
+						"%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns),
 		.ref = 1,
 	);
 
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c
index f4859f8..67be1ca 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.c
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -41,11 +41,6 @@ struct pts_ita_comp_tboot_t {
 	pts_comp_func_name_t *name;
 
 	/**
-	 * AIK keyid
-	 */
-	chunk_t keyid;
-
-	/**
 	 * Sub-component depth
 	 */
 	u_int32_t depth;
@@ -56,6 +51,11 @@ struct pts_ita_comp_tboot_t {
 	pts_database_t *pts_db;
 
 	/**
+	 * Primary key for AIK database entry
+	 */
+	int aik_id;
+
+	/**
 	 * Primary key for Component Functional Name database entry
 	 */
 	int cid;
@@ -201,51 +201,38 @@ METHOD(pts_component_t, verify, status_t,
 	chunk_t measurement, pcr_before, pcr_after;
 	status_t status;
 
+	this->aik_id = pts->get_aik_id(pts);
 	pcrs = pts->get_pcrs(pts);
 	measurement = evidence->get_measurement(evidence, &extended_pcr,
 								&algo, &transform, &measurement_time);
 
-	if (!this->keyid.ptr)
+	status = this->pts_db->get_comp_measurement_count(this->pts_db,
+									this->name, this->aik_id, algo,
+									&this->cid, &this->count);
+	if (status != SUCCESS)
 	{
-		if (!pts->get_aik_keyid(pts, &this->keyid))
-		{
-			return FAILED;
-		}
-		this->keyid = chunk_clone(this->keyid);
-
-		if (!this->pts_db)
-		{
-			DBG1(DBG_PTS, "pts database not available");
-			return FAILED;
-		}
-		status = this->pts_db->get_comp_measurement_count(this->pts_db,
-								this->name, this->keyid, algo, &this->cid,
-								&this->kid, &this->count);
-		if (status != SUCCESS)
-		{
-			return status;
-		}
-		vid = this->name->get_vendor_id(this->name);
-		name = this->name->get_name(this->name);
-		names = pts_components->get_comp_func_names(pts_components, vid);
+		return status;
+	}
+	vid = this->name->get_vendor_id(this->name);
+	name = this->name->get_name(this->name);
+	names = pts_components->get_comp_func_names(pts_components, vid);
 
-		if (this->count)
-		{
-			DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
-				 "measurements", this->count, pen_names, vid, names, name);
-		}
-		else
-		{
-			DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
-				 "measurements", pen_names, vid, names, name);
-			this->is_registering = TRUE;
-		}
+	if (this->count)
+	{
+		DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
+			 "measurements", this->count, pen_names, vid, names, name);
+	}
+	else
+	{
+		DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
+			 "measurements", pen_names, vid, names, name);
+		this->is_registering = TRUE;
 	}
 
 	if (this->is_registering)
 	{
 		status = this->pts_db->insert_comp_measurement(this->pts_db,
-								measurement, this->cid, this->kid,
+								measurement, this->cid, this->aik_id,
 								++this->seq_no, extended_pcr, algo);
 		if (status != SUCCESS)
 		{
@@ -282,30 +269,31 @@ METHOD(pts_component_t, verify, status_t,
 }
 
 METHOD(pts_component_t, finalize, bool,
-	pts_ita_comp_tboot_t *this, u_int8_t qualifier)
+	pts_ita_comp_tboot_t *this, u_int8_t qualifier, bio_writer_t *result)
 {
-	u_int32_t vid, name;
-	enum_name_t *names;
-
-	vid = this->name->get_vendor_id(this->name);
-	name = this->name->get_name(this->name);
-	names = pts_components->get_comp_func_names(pts_components, vid);
+	char result_buf[BUF_LEN];
 
 	if (this->is_registering)
 	{
 		/* close registration */
 		this->is_registering = FALSE;
 
-		DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence "
-					  "measurements", this->seq_no, pen_names, vid, names, name);
+		snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
+				 this->seq_no);
 	}
 	else if (this->seq_no < this->count)
 	{
-		DBG1(DBG_PTS, "%d of %d %N '%N' functional component evidence "
-					  "measurements missing", this->count - this->seq_no,
-					   this->count, pen_names, vid, names, name);
+		snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements "
+				 "missing", this->count - this->seq_no, this->count);
 		return FALSE;
 	}
+	else
+	{
+		snprintf(result_buf, BUF_LEN, "%d evidence measurements are ok",
+				 this->count);
+	}
+	DBG1(DBG_PTS, "%s", result_buf);
+	result->write_data(result, chunk_from_str(result_buf));
 
 	return TRUE;
 }
@@ -329,7 +317,7 @@ METHOD(pts_component_t, destroy, void,
 		if (this->is_registering)
 		{
 			count = this->pts_db->delete_comp_measurements(this->pts_db,
-													this->cid, this->kid);
+												this->cid, this->aik_id);
 			vid = this->name->get_vendor_id(this->name);
 			name = this->name->get_name(this->name);
 			names = pts_components->get_comp_func_names(pts_components, vid);
@@ -337,7 +325,6 @@ METHOD(pts_component_t, destroy, void,
 				 "evidence measurements", count, pen_names, vid, names, name);
 		}
 		this->name->destroy(this->name);
-		free(this->keyid.ptr);
 		free(this);
 	}
 }
diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c
index e3acd87..097e4c8 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.c
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c
@@ -49,7 +49,6 @@ struct pts_ita_comp_tgrub_t {
 	 */
 	pts_database_t *pts_db;
 
-
 	/**
 	 * Reference count
 	 */
@@ -126,7 +125,8 @@ METHOD(pts_component_t, verify, status_t,
 	pts_pcr_transform_t transform;
 	pts_pcr_t *pcrs;
 	time_t measurement_time;
-	chunk_t measurement, pcr_before, pcr_after;
+	chunk_t pcr_before, pcr_after;
+	chunk_t measurement __attribute__((unused));
 
 	pcrs = pts->get_pcrs(pts);
 	measurement = evidence->get_measurement(evidence, &extended_pcr,
@@ -155,7 +155,7 @@ METHOD(pts_component_t, verify, status_t,
 }
 
 METHOD(pts_component_t, finalize, bool,
-	pts_ita_comp_tgrub_t *this, u_int8_t qualifier)
+	pts_ita_comp_tgrub_t *this, u_int8_t qualifier, bio_writer_t *result)
 {
 	return FALSE;
 }
@@ -206,4 +206,3 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth,
 
 	return &this->public;
 }
-
diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h
index da339a5..71b1ad5 100644
--- a/src/libpts/pts/components/pts_component.h
+++ b/src/libpts/pts/components/pts_component.h
@@ -30,6 +30,7 @@ typedef struct pts_component_t pts_component_t;
 #include "pts/components/pts_comp_evidence.h"
 
 #include <library.h>
+#include <bio/bio_writer.h>
 
 /**
  * PTS Functional Component Interface 
@@ -85,9 +86,11 @@ struct pts_component_t {
 	 * and check for missing measurements
 	 *
 	 * @param qualifier		PTS Component Functional Name Qualifier
+	 * @param result		writer appending concise measurement result
 	 * @return				TRUE if finalization successful
 	 */
-	bool (*finalize)(pts_component_t *this, u_int8_t qualifier);
+	bool (*finalize)(pts_component_t *this, u_int8_t qualifier,
+					 bio_writer_t *result);
 
 	/**
 	 * Get a new reference to the PTS Functional Component
diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c
index 3ab9b92..2fff4c9 100644
--- a/src/libpts/pts/pts.c
+++ b/src/libpts/pts/pts.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -21,6 +22,10 @@
 #include <bio/bio_reader.h>
 
 #ifdef TSS_TROUSERS
+#ifdef _BASETSD_H_
+/* MinGW defines _BASETSD_H_, but TSS checks for _BASETSD_H */
+# define _BASETSD_H
+#endif
 #include <trousers/tss.h>
 #include <trousers/trousers.h>
 #else
@@ -34,7 +39,6 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/utsname.h>
 #include <libgen.h>
 #include <unistd.h>
 #include <errno.h>
@@ -88,9 +92,9 @@ struct private_pts_t {
 	chunk_t secret;
 
 	/**
-	 * Platform and OS Info
+	 * Primary key of platform entry in database
 	 */
-	char *platform_info;
+	int platform_id;
 
 	/**
 	 * TRUE if IMC-PTS, FALSE if IMV-PTS
@@ -118,6 +122,11 @@ struct private_pts_t {
  	certificate_t *aik;
 
 	/**
+	 * Primary key referening AIK in database
+	 */
+	int aik_id;
+
+	/**
 	 * Shadow PCR set
 	 */
 	pts_pcr_t *pcrs;
@@ -296,29 +305,23 @@ METHOD(pts_t, calculate_secret, bool,
  */
 static void print_tpm_version_info(private_pts_t *this)
 {
-	TPM_CAP_VERSION_INFO versionInfo;
-	UINT64 offset = 0;
-	TSS_RESULT result;
+	TPM_CAP_VERSION_INFO *info;
 
-	result = Trspi_UnloadBlob_CAP_VERSION_INFO(&offset,
-						this->tpm_version_info.ptr, &versionInfo);
-	if (result != TSS_SUCCESS)
+	info = (TPM_CAP_VERSION_INFO*)this->tpm_version_info.ptr;
+
+	if (this->tpm_version_info.len >=
+			sizeof(*info) - sizeof(info->vendorSpecific))
 	{
-		DBG1(DBG_PTS, "could not parse tpm version info: tss error 0x%x",
-			 result);
+		DBG2(DBG_PTS, "TPM Version Info: Chip Version: %u.%u.%u.%u, "
+			 "Spec Level: %u, Errata Rev: %u, Vendor ID: %.4s",
+			 info->version.major, info->version.minor,
+			 info->version.revMajor, info->version.revMinor,
+			 untoh16(&info->specLevel), info->errataRev, info->tpmVendorID);
 	}
 	else
 	{
-		DBG2(DBG_PTS, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu,"
-					  " Spec Level: %hu, Errata Rev: %hhu, Vendor ID: %.4s [%.*s]",
-					  versionInfo.version.major, versionInfo.version.minor,
-					  versionInfo.version.revMajor, versionInfo.version.revMinor,
-					  versionInfo.specLevel, versionInfo.errataRev,
-					  versionInfo.tpmVendorID, versionInfo.vendorSpecificSize,
-					  versionInfo.vendorSpecificSize ?
-					  (char*)versionInfo.vendorSpecific : "");
+		DBG1(DBG_PTS, "could not parse tpm version info");
 	}
-	free(versionInfo.vendorSpecific);
 }
 
 #else
@@ -330,22 +333,16 @@ static void print_tpm_version_info(private_pts_t *this)
 
 #endif /* TSS_TROUSERS */
 
-METHOD(pts_t, get_platform_info, char*,
+METHOD(pts_t, get_platform_id, int,
 	private_pts_t *this)
 {
-	return this->platform_info;
+	return this->platform_id;
 }
 
-METHOD(pts_t, set_platform_info, void,
-	private_pts_t *this, chunk_t name, chunk_t version)
+METHOD(pts_t, set_platform_id, void,
+	private_pts_t *this, int pid)
 {
-	int len = name.len + 1 + version.len + 1;
-
-	/* platform info is a concatenation of OS name and OS version */
-	free(this->platform_info);
-	this->platform_info = malloc(len);
-	snprintf(this->platform_info, len, "%.*s %.*s", (int)name.len, name.ptr,
-			(int)version.len, version.ptr);
+	this->platform_id = pid;
 }
 
 METHOD(pts_t, get_tpm_version_info, bool,
@@ -372,42 +369,31 @@ METHOD(pts_t, set_tpm_version_info, void,
  */
 static void load_aik_blob(private_pts_t *this)
 {
-	char *blob_path;
-	FILE *fp;
-	u_int32_t aikBlobLen;
+	char *path;
+	chunk_t *map;
 
-	blob_path = lib->settings->get_str(lib->settings,
+	path = lib->settings->get_str(lib->settings,
 						"%s.plugins.imc-attestation.aik_blob", NULL, lib->ns);
-
-	if (blob_path)
+	if (path)
 	{
-		/* Read aik key blob from a file */
-		if ((fp = fopen(blob_path, "r")) == NULL)
-		{
-			DBG1(DBG_PTS, "unable to open AIK Blob file: %s", blob_path);
-			return;
-		}
-
-		fseek(fp, 0, SEEK_END);
-		aikBlobLen = ftell(fp);
-		fseek(fp, 0L, SEEK_SET);
-
-		this->aik_blob = chunk_alloc(aikBlobLen);
-		if (fread(this->aik_blob.ptr, 1, aikBlobLen, fp) == aikBlobLen)
+		map = chunk_map(path, FALSE);
+		if (map)
 		{
-			DBG2(DBG_PTS, "loaded AIK Blob from '%s'", blob_path);
-			DBG3(DBG_PTS, "AIK Blob: %B", &this->aik_blob);
+			DBG2(DBG_PTS, "loaded AIK Blob from '%s'", path);
+			DBG3(DBG_PTS, "AIK Blob: %B", map);
+			this->aik_blob = chunk_clone(*map);
+			chunk_unmap(map);
 		}
 		else
 		{
-			DBG1(DBG_PTS, "unable to read AIK Blob file '%s'", blob_path);
-			chunk_free(&this->aik_blob);
+			DBG1(DBG_PTS, "unable to map AIK Blob file '%s': %s",
+				 path, strerror(errno));
 		}
-		fclose(fp);
-		return;
 	}
-
-	DBG1(DBG_PTS, "AIK Blob is not available");
+	else
+	{
+		DBG1(DBG_PTS, "AIK Blob is not available");
+	}
 }
 
 /**
@@ -421,7 +407,7 @@ static void load_aik(private_pts_t *this)
 	cert_path = lib->settings->get_str(lib->settings,
 						"%s.plugins.imc-attestation.aik_cert", NULL, lib->ns);
 	key_path = lib->settings->get_str(lib->settings,
-						"%s.plugins.imc-attestation.aik_key", NULL, lib->ns);
+						"%s.plugins.imc-attestation.aik_pubkey", NULL, lib->ns);
 
 	if (cert_path)
 	{
@@ -456,37 +442,17 @@ METHOD(pts_t, get_aik, certificate_t*,
 }
 
 METHOD(pts_t, set_aik, void,
-	private_pts_t *this, certificate_t *aik)
+	private_pts_t *this, certificate_t *aik, int aik_id)
 {
 	DESTROY_IF(this->aik);
 	this->aik = aik->get_ref(aik);
+	this->aik_id = aik_id;
 }
 
-METHOD(pts_t, get_aik_keyid, bool,
-	private_pts_t *this, chunk_t *keyid)
+METHOD(pts_t, get_aik_id, int,
+	private_pts_t *this)
 {
-	public_key_t *public;
-	bool success;
-
-	if (!this->aik)
-	{
-		DBG1(DBG_PTS, "no AIK certificate available");
-		return FALSE;
-	}
-	public = this->aik->get_public_key(this->aik);
-	if (!public)
-	{
-		DBG1(DBG_PTS, "no AIK public key available");
-		return FALSE;
-	}
-	success = public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, keyid);
-	if (!success)
-	{
-		DBG1(DBG_PTS, "no SHA-1 AIK public key info ID available");
-	}
-	public->destroy(public);
-
-	return success;
+	return this->aik_id;
 }
 
 METHOD(pts_t, is_path_valid, bool,
@@ -557,6 +523,7 @@ static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
 	{
 		this->type = PTS_FILE_FIFO;
 	}
+#ifndef WIN32
 	else if (S_ISLNK(st.st_mode))
 	{
 		this->type = PTS_FILE_SYM_LINK;
@@ -565,6 +532,7 @@ static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
 	{
 		this->type = PTS_FILE_SOCKET;
 	}
+#endif /* WIN32 */
 	else
 	{
 		this->type = PTS_FILE_OTHER;
@@ -644,7 +612,8 @@ METHOD(pts_t, read_pcr, bool,
 	TSS_HCONTEXT hContext;
 	TSS_HTPM hTPM;
 	TSS_RESULT result;
-	chunk_t rgbPcrValue;
+	BYTE *buf;
+	UINT32 len;
 
 	bool success = FALSE;
 
@@ -665,12 +634,12 @@ METHOD(pts_t, read_pcr, bool,
 	{
 		goto err;
 	}
-	result = Tspi_TPM_PcrRead(hTPM, pcr_num, (UINT32*)&rgbPcrValue.len, &rgbPcrValue.ptr);
+	result = Tspi_TPM_PcrRead(hTPM, pcr_num, &len, &buf);
 	if (result != TSS_SUCCESS)
 	{
 		goto err;
 	}
-	*pcr_value = chunk_clone(rgbPcrValue);
+	*pcr_value = chunk_clone(chunk_create(buf, len));
 	DBG3(DBG_PTS, "PCR %d value:%B", pcr_num, pcr_value);
 	success = TRUE;
 
@@ -1093,7 +1062,6 @@ METHOD(pts_t, destroy, void,
 	free(this->initiator_nonce.ptr);
 	free(this->responder_nonce.ptr);
 	free(this->secret.ptr);
-	free(this->platform_info);
 	free(this->aik_blob.ptr);
 	free(this->tpm_version_info.ptr);
 	free(this);
@@ -1187,13 +1155,13 @@ pts_t *pts_create(bool is_imc)
 			.get_my_public_value = _get_my_public_value,
 			.set_peer_public_value = _set_peer_public_value,
 			.calculate_secret = _calculate_secret,
-			.get_platform_info = _get_platform_info,
-			.set_platform_info = _set_platform_info,
+			.get_platform_id = _get_platform_id,
+			.set_platform_id = _set_platform_id,
 			.get_tpm_version_info = _get_tpm_version_info,
 			.set_tpm_version_info = _set_tpm_version_info,
 			.get_aik = _get_aik,
 			.set_aik = _set_aik,
-			.get_aik_keyid = _get_aik_keyid,
+			.get_aik_id = _get_aik_id,
 			.is_path_valid = _is_path_valid,
 			.get_metadata = _get_metadata,
 			.read_pcr = _read_pcr,
diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h
index 11154aa..fead588 100644
--- a/src/libpts/pts/pts.h
+++ b/src/libpts/pts/pts.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -162,19 +163,18 @@ struct pts_t {
 	bool (*calculate_secret) (pts_t *this);
 
 	/**
-	 * Get Platform and OS Info
+	 * Get primary key of platform entry in database
 	 *
 	 * @return					Platform and OS info
 	 */
-	char* (*get_platform_info)(pts_t *this);
+	int (*get_platform_id)(pts_t *this);
 
 	/**
-	 * Set Platform and OS Info
+	 * Set primary key of platform entry in database
 	 *
-	 * @param name				OS name
-	 * @param version			OS version
+	 * @param pid				Primary key of platform entry in database
 	 */
-	void (*set_platform_info)(pts_t *this, chunk_t name, chunk_t version);
+	void (*set_platform_id)(pts_t *this, int pid);
 
 	/**
 	 * Get TPM 1.2 Version Info
@@ -202,16 +202,16 @@ struct pts_t {
 	 * Set Attestation Identity Certificate or Public Key
 	 *
 	 * @param aik				AIK Certificate or Public Key
+	 * @param aik_id			Primary key referencing AIK in database
 	 */
-	void (*set_aik)(pts_t *this, certificate_t *aik);
+	void (*set_aik)(pts_t *this, certificate_t *aik, int aik_id);
 
 	/**
-	 * Get SHA-1 Attestation Identity Public Key Info ID
+	 * Get primary key referencing AIK in database
 	 *
-	 * @param keyid				AIK ID
-	 * @return					TRUE if AIK ID exists
+	 * @return					Primary key referencing AIK in database
 	 */
-	bool (*get_aik_keyid)(pts_t *this, chunk_t *keyid);
+	int (*get_aik_id)(pts_t *this);
 
 	/**
 	 * Check whether path is valid file/directory on filesystem
diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c
index fda644a..d7b85c1 100644
--- a/src/libpts/pts/pts_database.c
+++ b/src/libpts/pts/pts_database.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * Copyright (C) 2011-2012 Sansar Choinyambuu
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -47,7 +48,7 @@ METHOD(pts_database_t, get_pathname, char*,
 	private_pts_database_t *this, bool is_dir, int id)
 {
 	enumerator_t *e;
-	char *path, *name, *pathname;
+	char *path, *name, *sep, *pathname = NULL;
 
 	if (is_dir)
 	{
@@ -69,11 +70,21 @@ METHOD(pts_database_t, get_pathname, char*,
 				"SELECT d.path, f.name FROM files AS f "
 				"JOIN directories AS d ON d.id = f.dir WHERE f.id = ?",
 				 DB_INT, id, DB_TEXT, DB_TEXT);
-		if (!e || !e->enumerate(e, &path, &name) ||
-			asprintf(&pathname, "%s%s%s",
-					 path, streq(path, "/") ? "" : "/", name) == -1)
+		if (e && e->enumerate(e, &path, &name))
 		{
-			pathname = NULL;
+			if (path[0] == '/')
+			{	/* Unix style absolute path */
+				sep = "/";
+			}
+			else
+			{	/* Windows absolute path */
+				sep = "\\";
+			}
+			if (asprintf(&pathname, "%s%s%s",
+						 path, streq(path, "/") ? "" : sep, name) == -1)
+			{
+				pathname = NULL;
+			}
 		}
 	}
 	DESTROY_IF(e);
@@ -82,7 +93,7 @@ METHOD(pts_database_t, get_pathname, char*,
 }
 
 METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
-	private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
+	private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
 	bool is_dir, int id)
 {
 	enumerator_t *e;
@@ -90,73 +101,34 @@ METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
 	if (is_dir)
 	{
 		e = this->db->query(this->db,
-				"SELECT f.name, fh.hash FROM file_hashes AS fh "
+				"SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
 				"JOIN files AS f ON f.id = fh.file "
-				"JOIN products AS p ON p.id = fh.product "
 				"JOIN directories as d ON d.id = f.dir "
-				"WHERE p.name = ? AND fh.algo = ? AND d.id = ? "
+				"WHERE fh.product = ? AND fh.algo = ? AND d.id = ? "
 				"ORDER BY f.name",
-				DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB);
+				DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
 	}
 	else
 	{
 		e = this->db->query(this->db,
-				"SELECT f.name, fh.hash FROM file_hashes AS fh "
+				"SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
 				"JOIN files AS f ON f.id = fh.file "
-				"JOIN products AS p ON p.id = fh.product "
-				"WHERE p.name = ? AND fh.algo = ? AND fh.file = ?",
-				DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB);
+				"WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
+				DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
 	}
 	return e;
 }
 
-METHOD(pts_database_t, check_aik_keyid, status_t,
-	private_pts_database_t *this, chunk_t keyid, int *kid)
-{
-	enumerator_t *e;
-
-	/* If the AIK is registered get the primary key */
-	e = this->db->query(this->db,
-				"SELECT id FROM keys WHERE keyid = ?", DB_BLOB, keyid, DB_INT);
-	if (!e)
-	{
-		DBG1(DBG_PTS, "no database query enumerator returned");
-		return FAILED;
-	}
-	if (!e->enumerate(e, kid))
-	{
-		DBG1(DBG_PTS, "AIK %#B is not registered in database", &keyid);
-		e->destroy(e);
-		return FAILED;
-	}
-	e->destroy(e);
-
-	return SUCCESS;
-}
-
 METHOD(pts_database_t, add_file_measurement, status_t,
-	private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
+	private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
 	chunk_t measurement, char *filename, bool is_dir, int id)
 {
 	enumerator_t *e;
 	char *name;
 	chunk_t hash_value;
-	int hash_id, fid, pid = 0;
+	int hash_id, fid;
 	status_t status = SUCCESS;
 
-	/* get primary key of product string */
-	e = this->db->query(this->db,
-			"SELECT id FROM products WHERE name = ?", DB_TEXT, product, DB_INT);
-	if (e)
-	{
-		e->enumerate(e, &pid);
-		e->destroy(e);
-	}
-	if (pid == 0)
-	{
-		return FAILED;
-	}
-
 	if (is_dir)
 	{
 		/* does filename entry already exist? */
@@ -242,18 +214,16 @@ METHOD(pts_database_t, add_file_measurement, status_t,
 	return status;
 }
 
-METHOD(pts_database_t, check_file_measurement, status_t,
-	private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
-	chunk_t measurement, char *filename)
+METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*,
+	private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
+	char *filename)
 {
 	enumerator_t *e;
-	chunk_t hash;
-	status_t status = NOT_FOUND;
 	char *dir, *file;
 
 	if (strlen(filename) < 1)
 	{
-		return INVALID_ARG;
+		return NULL;
 	}
 
 	/* separate filename into directory and basename components */
@@ -265,84 +235,40 @@ METHOD(pts_database_t, check_file_measurement, status_t,
 		e = this->db->query(this->db,
 				"SELECT fh.hash FROM file_hashes AS fh "
 				"JOIN files AS f ON f.id = fh.file "
-				"JOIN products AS p ON p.id = fh.product "
-				"WHERE p.name = ? AND f.name = ? AND fh.algo = ?",
-		DB_TEXT, product, DB_TEXT, file, DB_INT, algo, DB_BLOB);
+				"WHERE fh.product = ? AND f.name = ? AND fh.algo = ?",
+				DB_INT, pid, DB_TEXT, file, DB_INT, algo, DB_BLOB);
 	}
 	else
 	{	/* absolute pathname */
-		bool dir_found;
 		int did;
 
 		/* find directory entry first */
 		e = this->db->query(this->db,
 				"SELECT id FROM directories WHERE path = ?",
 				DB_TEXT, dir, DB_INT);
-		if (!e)
+
+		if (!e || !e->enumerate(e, &did))
 		{
-			status = FAILED;
 			goto err;
 		}
-		dir_found = e->enumerate(e, &did);
 		e->destroy(e);
 
-		if (!dir_found)
-		{
-			status = NOT_FOUND;
-			goto err;
-		}
 		e = this->db->query(this->db,
 				"SELECT fh.hash FROM file_hashes AS fh "
 				"JOIN files AS f ON f.id = fh.file "
-				"JOIN products AS p ON p.id = fh.product "
-				"WHERE p.name = ? AND f.dir = ? AND f.name = ? AND fh.algo = ?",
-				DB_TEXT, product, DB_INT, did, DB_TEXT, file, DB_INT, algo,
-				DB_BLOB);
-	}
-	if (!e)
-	{
-		status = FAILED;
-		goto err;
+				"WHERE fh.product = ? AND f.dir = ? AND f.name = ? AND fh.algo = ?",
+				DB_INT, pid, DB_INT, did, DB_TEXT, file, DB_INT, algo, DB_BLOB);
 	}
-	while (e->enumerate(e, &hash))
-	{
-		/* with relative filenames there might be multiple entries */
-		if (chunk_equals(measurement, hash))
-		{
-			status = SUCCESS;
-			break;
-		}
-		else
-		{
-			status = VERIFY_ERROR;
-		}
-	}
-	e->destroy(e);
 
 err:
 	free(file);
 	free(dir);
 
-	return status;
-}
-
-METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
-	private_pts_database_t *this, int kid)
-{
-	enumerator_t *e;
-
-	/* look for all entries belonging to an AIK in the components table */
-	e = this->db->query(this->db,
-				"SELECT c.vendor_id, c.name, c.qualifier, kc.depth "
- 				"FROM components AS c "
-				"JOIN key_component AS kc ON c.id = kc.component "
-				"WHERE kc.key = ? ORDER BY kc.seq_no",
-				DB_INT, kid, DB_INT, DB_INT, DB_INT, DB_INT);
 	return e;
 }
 
 METHOD(pts_database_t, check_comp_measurement, status_t,
-	private_pts_database_t *this, chunk_t measurement, int cid, int kid,
+	private_pts_database_t *this, chunk_t measurement, int cid, int aik_id,
 	int seq_no, int pcr, pts_meas_algorithms_t algo)
 {
 	enumerator_t *e;
@@ -353,7 +279,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
 					"SELECT hash FROM component_hashes "
 					"WHERE component = ?  AND key = ? "
 					"AND seq_no = ? AND pcr = ? AND algo = ? ",
-					DB_INT, cid, DB_INT, kid, DB_INT, seq_no,
+					DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no,
 					DB_INT, pcr, DB_INT, algo, DB_BLOB);
 	if (!e)
 	{
@@ -390,7 +316,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
 }
 
 METHOD(pts_database_t, insert_comp_measurement, status_t,
-	private_pts_database_t *this, chunk_t measurement, int cid, int kid,
+	private_pts_database_t *this, chunk_t measurement, int cid, int aik_id,
 	int seq_no, int pcr, pts_meas_algorithms_t algo)
 {
 	int id;
@@ -399,7 +325,7 @@ METHOD(pts_database_t, insert_comp_measurement, status_t,
 					"INSERT INTO component_hashes "
 					"(component, key, seq_no, pcr, algo, hash) "
 					"VALUES (?, ?, ?, ?, ?, ?)",
-					DB_INT, cid, DB_INT, kid, DB_INT, seq_no, DB_INT, pcr,
+					DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no, DB_INT, pcr,
 					DB_INT, algo, DB_BLOB, measurement) == 1)
 	{
 		return SUCCESS;
@@ -410,17 +336,17 @@ METHOD(pts_database_t, insert_comp_measurement, status_t,
 }
 
 METHOD(pts_database_t, delete_comp_measurements, int,
-	private_pts_database_t *this, int cid, int kid)
+	private_pts_database_t *this, int cid, int aik_id)
 {
 	return this->db->execute(this->db, NULL,
 					"DELETE FROM component_hashes "
 					"WHERE component = ? AND key = ?",
-					DB_INT, cid, DB_INT, kid);
+					DB_INT, cid, DB_INT, aik_id);
 }
 
 METHOD(pts_database_t, get_comp_measurement_count, status_t,
 	private_pts_database_t *this, pts_comp_func_name_t *comp_name,
-	chunk_t keyid, pts_meas_algorithms_t algo, int *cid, int *kid, int *count)
+	int aik_id, pts_meas_algorithms_t algo, int *cid, int *count)
 {
 	enumerator_t *e;
 	status_t status = SUCCESS;
@@ -428,11 +354,6 @@ METHOD(pts_database_t, get_comp_measurement_count, status_t,
 	/* Initialize count */
 	*count = 0;
 
-	if (_check_aik_keyid(this, keyid, kid) != SUCCESS)
-	{
-		return FAILED;
-	}
-
 	/* Get the primary key of the Component Functional Name */
 	e = this->db->query(this->db,
 				"SELECT id FROM components "
@@ -458,7 +379,7 @@ METHOD(pts_database_t, get_comp_measurement_count, status_t,
 	e = this->db->query(this->db,
 				"SELECT COUNT(*) FROM component_hashes AS ch "
 				"WHERE component = ?  AND key = ? AND algo = ?",
-				DB_INT, *cid, DB_INT, *kid, DB_INT, algo, DB_INT);
+				DB_INT, *cid, DB_INT, aik_id, DB_INT, algo, DB_INT);
 	if (!e)
 	{
 		DBG1(DBG_PTS, "no database query enumerator returned");
@@ -495,11 +416,9 @@ pts_database_t *pts_database_create(imv_database_t *imv_db)
 	INIT(this,
 		.public = {
 			.get_pathname = _get_pathname,
-			.create_comp_evid_enumerator = _create_comp_evid_enumerator,
 			.create_file_hash_enumerator = _create_file_hash_enumerator,
-			.check_aik_keyid = _check_aik_keyid,
 			.add_file_measurement = _add_file_measurement,
-			.check_file_measurement = _check_file_measurement,
+			.create_file_meas_enumerator = _create_file_meas_enumerator,
 			.check_comp_measurement = _check_comp_measurement,
 			.insert_comp_measurement = _insert_comp_measurement,
 			.delete_comp_measurements = _delete_comp_measurements,
@@ -511,4 +430,3 @@ pts_database_t *pts_database_create(imv_database_t *imv_db)
 
 	return &this->public;
 }
-
diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h
index eb8aca3..a6c9fb3 100644
--- a/src/libpts/pts/pts_database.h
+++ b/src/libpts/pts/pts_database.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -47,37 +47,20 @@ struct pts_database_t {
 	/**
 	* Get stored measurement hash for single file or directory entries
 	*
-	* @param product		Software product (os, vpn client, etc.)
+	* @param pid	 		Primary key of software product in database
 	* @param algo			Hash algorithm used for measurement
 	* @param is_dir			TRUE if directory was measured
 	* @param id				Primary key of measured file/directory
 	* @return				Enumerator over all matching measurement hashes
 	*/
 	enumerator_t* (*create_file_hash_enumerator)(pts_database_t *this,
-								char *product, pts_meas_algorithms_t algo,
+								int pid, pts_meas_algorithms_t algo,
 								bool is_dir, int id);
 
 	/**
-	* Check if an AIK given by its keyid is registered in the database
-	*
-	* @param keyid			AIK keyid (SHA-1 hash of the AIK public key info)
-	* @param kid			Primary key of AIK entry in keys table
-	* @return				SUCCESS if AIK is present, FAILED otherwise
-	*/
-	status_t (*check_aik_keyid)(pts_database_t *this, chunk_t keyid, int *kid);
-
-	/**
-	* Get functional components to request evidence of
-	*
-	* @param kid			Primary key of AIK entry in keys table
-	* @return				Enumerator over all matching components
-	*/
-	enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this, int kid);
-
-	/**
 	* Add PTS file measurement reference value
 	*
-	* @param product		Software product (os, vpn client, etc.)
+	* @param pid			Primary key of software product in database
 	* @param algo			File measurement hash algorithm used
 	* @param measurement	File measurement hash
 	* @param filename		Optional name of the file to be checked
@@ -85,37 +68,36 @@ struct pts_database_t {
 	* @param id				Primary key into direcories/files table
 	* @return				Status
 	*/
-	status_t (*add_file_measurement)(pts_database_t *this, char *product,
+	status_t (*add_file_measurement)(pts_database_t *this, int pid,
 									 pts_meas_algorithms_t algo,
 									 chunk_t measurement, char *filename,
 									 bool is_dir, int id);
 
 	/**
-	* Check PTS file measurement against reference stored in database
+	* Get PTS measurement[s] for a given filename stored in database
 	*
-	* @param product		Software product (os, vpn client, etc.)
+	* @param pid			Primary key of software product in database
 	* @param algo			File measurement hash algorithm used
-	* @param measurement	File measurement hash
-	* @param filename		Optional name of the file to be checked
-	* @return				Status
+	* @param filename		Name of the file to be checked
+	* @return				Enumerator over all matching measurement hashes
 	*/
-	status_t (*check_file_measurement)(pts_database_t *this, char *product,
-									   pts_meas_algorithms_t algo,
-									   chunk_t measurement, char *filename);
+	enumerator_t* (*create_file_meas_enumerator)(pts_database_t *this, int pid,
+												 pts_meas_algorithms_t algo,
+												 char *filename);
 
 	/**
 	* Check a functional component measurement against value stored in database
 	*
 	* @param measurement	measurement hash
 	* @param cid			Primary key of Component Functional Name entry
-	* @param kid			Primary key of AIK entry in keys table
+	* @param aik_id			Primary key of AIK entry in database
 	* @param seq_no			Measurement sequence number
 	* @param prc			Number of the PCR the measurement was extended into
 	* @param algo			Hash algorithm used for measurement
 	* @return				SUCCESS if check was successful
 	*/
 	status_t (*check_comp_measurement)(pts_database_t *this, chunk_t measurement,
-									   int cid, int kid, int seq_no, int pcr,
+									   int cid, int aik_id, int seq_no, int pcr,
 									   pts_meas_algorithms_t algo);
 
 	/**
@@ -123,40 +105,38 @@ struct pts_database_t {
 	*
 	* @param measurement	Measurement hash
 	* @param cid			Primary key of Component Functional Name entry
-	* @param kid			Primary key of AIK entry in keys table
+	* @param aik_id			Primary key of AIK entry in database
 	* @param seq_no			Measurement sequence number
 	* @param prc			Number of the PCR the measurement was extended into
 	* @param algo			Hash algorithm used for measurement
 	* @return				SUCCESS if INSERT was successful
 	*/
 	status_t (*insert_comp_measurement)(pts_database_t *this, chunk_t measurement,
-										int cid, int kid, int seq_no, int pcr,
+										int cid, int aik_id, int seq_no, int pcr,
 										pts_meas_algorithms_t algo);
 
 	/**
 	* Delete functional component measurements from the database
 	*
 	* @param cid			Primary key of Component Functional Name entry
-	* @param kid			Primary key of AIK entry in keys table
+	* @param aik_id			Primary key of AIK entry in database
 	* @return				number of deleted measurement entries
 	*/
-	int (*delete_comp_measurements)(pts_database_t *this, int cid, int kid);
+	int (*delete_comp_measurements)(pts_database_t *this, int cid, int aik_id);
 
 	/**
 	* Get the number of measurements for a functional component and AIK
 	*
 	* @param comp_name		Component Functional Name
-	* @param keyid			SHA-1 hash of AIK public key info
+	* @param aik_id			Primary key of AIK entry in database
 	* @param algo			Hash algorithm used for measurement
 	* @param cid			Primary key of Component Functional Name entry
-	* @param kid			Primary key of AIK entry in keys table
 	* @param count			measurement count
 	* @return				SUCCESS if COUNT was successful
 	*/
 	status_t (*get_comp_measurement_count)(pts_database_t *this,
-							pts_comp_func_name_t *comp_name, chunk_t keyid,
-							pts_meas_algorithms_t algo, int *cid, int *kid,
-							int *count);
+							pts_comp_func_name_t *comp_name, int aik_id,
+							pts_meas_algorithms_t algo, int *cid, int *count);
 
 	/**
 	* Destroys a pts_database_t object.
diff --git a/src/libpts/pts/pts_file_meas.c b/src/libpts/pts/pts_file_meas.c
index 77a0957..478892a 100644
--- a/src/libpts/pts/pts_file_meas.c
+++ b/src/libpts/pts/pts_file_meas.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -112,19 +113,43 @@ METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
 }
 
 METHOD(pts_file_meas_t, check, bool,
-	private_pts_file_meas_t *this, pts_database_t *pts_db, char *product,
+	private_pts_file_meas_t *this, pts_database_t *pts_db, int pid,
 	pts_meas_algorithms_t algo)
 {
-	enumerator_t *enumerator;
+	enumerator_t *enumerator, *e;
 	entry_t *entry;
+	chunk_t hash;
 	int count_ok = 0, count_not_found = 0, count_differ = 0;
 	status_t status;
 
 	enumerator = this->list->create_enumerator(this->list);
 	while (enumerator->enumerate(enumerator, &entry))
 	{
-		status = pts_db->check_file_measurement(pts_db, product, algo,
-									entry->measurement, entry->filename);
+		status = NOT_FOUND;
+
+		e = pts_db->create_file_meas_enumerator(pts_db, pid, algo,
+												entry->filename);
+		if (e)
+		{
+			while (e->enumerate(e, &hash))
+			{
+				if (chunk_equals(entry->measurement, hash))
+				{
+					status = SUCCESS;
+					break;
+				}
+				else
+				{
+					status = VERIFY_ERROR;
+				}
+			}
+			e->destroy(e);
+		}
+		else
+		{
+			status = FAILED;
+		}
+
 		switch (status)
 		{
 			case SUCCESS:
@@ -159,47 +184,75 @@ METHOD(pts_file_meas_t, check, bool,
 METHOD(pts_file_meas_t, verify, bool,
 	private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
 {
+	int fid, fid_last = 0;
 	char *filename;
 	chunk_t measurement;
 	entry_t *entry;
-	enumerator_t *enumerator;
-	bool found, success = TRUE;
+	enumerator_t *enumerator = NULL;
+	bool found = FALSE, match = FALSE, success = TRUE;
 
-	while (e_hash->enumerate(e_hash, &filename, &measurement))
+	while (e_hash->enumerate(e_hash, &fid, &filename, &measurement))
 	{
-		found = FALSE;
-
-		enumerator = this->list->create_enumerator(this->list);
-		while (enumerator->enumerate(enumerator, &entry))
+		if (fid != fid_last)
 		{
-			if (!is_dir || streq(filename, entry->filename))
+			if (found && !match)
 			{
-				found = TRUE;
-				break;
+				/* no matching hash value found for last filename */
+				success = FALSE;
+				DBG1(DBG_PTS, "  %#B for '%s' is incorrect",
+					 &entry->measurement, entry->filename);
+				enumerator->destroy(enumerator);
 			}
-		}
-		enumerator->destroy(enumerator);
 
-		if (!found)
-		{
-			DBG1(DBG_PTS, "  no measurement found for '%s'", filename);
-			success = FALSE;
-			continue;
-		}
-		if (chunk_equals(measurement, entry->measurement))
-		{
-			DBG2(DBG_PTS, "  %#B for '%s' is ok", &measurement, filename);
-		}
-		else
-		{
-			DBG1(DBG_PTS, "  %#B for '%s' is incorrect", &measurement, filename);
-			success = FALSE;
+			/* get a new filename from the database */
+			found = FALSE;
+			match = FALSE;
+			fid_last = fid;
+
+			/**
+			 * check if we find an entry for this filename
+			 * in the PTS measurement list
+			*/
+			enumerator = this->list->create_enumerator(this->list);
+			while (enumerator->enumerate(enumerator, &entry))
+			{
+				if (!is_dir || streq(filename, entry->filename))
+				{
+					found = TRUE;
+					break;
+				}
+			}
+
+			/* no PTS measurement returned for this filename */ 
+			if (!found)
+			{
+				success = FALSE;
+				DBG1(DBG_PTS, "  no measurement found for '%s'", filename);
+				enumerator->destroy(enumerator);
+			}
 		}
-		if (!is_dir)
+
+		if (found && !match)
 		{
-			break;
+			if (chunk_equals(measurement, entry->measurement))
+			{
+				match = TRUE;
+				DBG2(DBG_PTS, "  %#B for '%s' is ok",
+					 &entry->measurement, entry->filename);
+				enumerator->destroy(enumerator);
+			}
 		}
 	}
+
+	if (found && !match)
+	{
+		/* no matching hash value found for the very last filename */
+		success = FALSE;
+		DBG1(DBG_PTS, "  %#B for '%s' is incorrect",
+			 &entry->measurement, entry->filename);
+			enumerator->destroy(enumerator);
+	}
+	
 	return success;
 }
 
diff --git a/src/libpts/pts/pts_file_meas.h b/src/libpts/pts/pts_file_meas.h
index a13bb29..4bf28e2 100644
--- a/src/libpts/pts/pts_file_meas.h
+++ b/src/libpts/pts/pts_file_meas.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -65,11 +66,11 @@ struct pts_file_meas_t {
 	 * Check PTS File Measurements against reference value in the database
 	 *
 	 * @param db			PTS Measurement database
-	 * @param product		Software product (os, vpn client, etc.)
+	 * @param pid			Primary key of software product in database
 	 * @param algo			PTS Measurement algorithm used
 	 * @return				TRUE if all measurements agreed
 	 */
-	bool (*check)(pts_file_meas_t *this, pts_database_t *db, char* product,
+	bool (*check)(pts_file_meas_t *this, pts_database_t *db, int pid,
 				  pts_meas_algorithms_t algo);
 
 	/**
diff --git a/src/libpts/pts/pts_ima_bios_list.c b/src/libpts/pts/pts_ima_bios_list.c
new file mode 100644
index 0000000..5051b6c
--- /dev/null
+++ b/src/libpts/pts/pts_ima_bios_list.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2011-2014 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 "pts_ima_bios_list.h"
+
+#include <utils/debug.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+typedef struct private_pts_ima_bios_list_t private_pts_ima_bios_list_t;
+typedef struct bios_entry_t bios_entry_t;
+typedef enum event_type_t event_type_t;
+
+enum event_type_t {
+	/* BIOS Events (TCG PC Client Specification for Conventional BIOS 1.21) */
+	EV_PREBOOT_CERT =                  0x00000000,
+	EV_POST_CODE =                     0x00000001,
+	EV_UNUSED =                        0x00000002,
+	EV_NO_ACTION =                     0x00000003,
+	EV_SEPARATOR =                     0x00000004,
+	EV_ACTION =                        0x00000005,
+	EV_EVENT_TAG =                     0x00000006,
+	EV_S_CRTM_CONTENTS =               0x00000007,
+	EV_S_CRTM_VERSION =                0x00000008,
+	EV_CPU_MICROCODE =                 0x00000009,
+	EV_PLATFORM_CONFIG_FLAGS =         0x0000000A,
+	EV_TABLE_OF_DEVICES =              0x0000000B,
+	EV_COMPACT_HASH =                  0x0000000C,
+	EV_IPL =                           0x0000000D,
+	EV_IPL_PARTITION_DATA =            0x0000000E,
+	EV_NONHOST_CODE =                  0x0000000F,
+	EV_NONHOST_CONFIG =                0x00000010,
+	EV_NONHOST_INFO =                  0x00000011,
+	EV_OMIT_BOOT_DEVICE_EVENTS =       0x00000012,
+
+	/* EFI Events (TCG EFI Platform Specification 1.22) */
+	EV_EFI_EVENT_BASE =                0x80000000,
+	EV_EFI_VARIABLE_DRIVER_CONFIG =    0x80000001,
+	EV_EFI_VARIABLE_BOOT =             0x80000002,
+	EV_EFI_BOOT_SERVICES_APPLICATION = 0x80000003,
+	EV_EFI_BOOT_SERVICES_DRIVER =      0x80000004,
+	EV_EFI_RUNTIME_SERVICES_DRIVER =   0x80000005,
+	EV_EFI_GPT_EVENT =                 0x80000006,
+	EV_EFI_ACTION =                    0x80000007,
+	EV_EFI_PLATFORM_FIRMWARE_BLOB =    0x80000008,
+	EV_EFI_HANDOFF_TABLES =            0x80000009,
+
+	EV_EFI_VARIABLE_AUTHORITY =        0x800000E0
+};
+
+ENUM_BEGIN(event_type_names, EV_PREBOOT_CERT, EV_OMIT_BOOT_DEVICE_EVENTS,
+	"Preboot Cert",
+	"POST Code",
+	"Unused",
+	"No Action",
+	"Separator",
+	"Action",
+	"Event Tag",
+	"S-CRTM Contents",
+	"S-CRTM Version",
+	"CPU Microcode",
+	"Platform Config Flags",
+	"Table of Devices",
+	"Compact Hash",
+	"IPL",
+	"IPL Partition Data",
+	"Nonhost Code",
+	"Nonhost Config",
+	"Nonhost Info",
+	"Omit Boot Device Events"
+);
+
+ENUM_NEXT(event_type_names, EV_EFI_EVENT_BASE, EV_EFI_HANDOFF_TABLES,
+							EV_OMIT_BOOT_DEVICE_EVENTS,
+	"EFI Event Base",
+	"EFI Variable Driver Config",
+	"EFI Variable Boot",
+	"EFI Boot Services Application",
+	"EFI Boot Services Driver",
+	"EFI Runtime Services Driver",
+	"EFI GPT Event",
+	"EFI Action",
+	"EFI Platform Firmware Blob",
+	"EFI Handoff Tables"
+);
+ENUM_NEXT(event_type_names, EV_EFI_VARIABLE_AUTHORITY, EV_EFI_VARIABLE_AUTHORITY,
+							EV_EFI_HANDOFF_TABLES,
+	"EFI Variable Authority"
+);
+ENUM_END(event_type_names, EV_EFI_VARIABLE_AUTHORITY);
+
+/**
+ * Private data of a pts_ima_bios_list_t object.
+ *
+ */
+struct private_pts_ima_bios_list_t {
+
+	/**
+	 * Public pts_ima_bios_list_t interface.
+	 */
+	pts_ima_bios_list_t public;
+
+	/**
+	 * List of BIOS measurement entries
+	 */
+	linked_list_t *list;
+
+	/**
+	 * Time when BIOS measurements were taken
+	 */
+	time_t creation_time;
+
+};
+
+/**
+ * Linux IMA BIOS measurement entry
+ */
+struct bios_entry_t {
+
+	/**
+	 * PCR register
+	 */
+	uint32_t pcr;
+
+	/**
+	 * SHA1 measurement hash
+	 */
+	chunk_t measurement;
+};
+
+/**
+ * Free a bios_entry_t object
+ */
+static void free_bios_entry(bios_entry_t *this)
+{
+	free(this->measurement.ptr);
+	free(this);
+}
+
+METHOD(pts_ima_bios_list_t, get_time, time_t,
+	private_pts_ima_bios_list_t *this)
+{
+	return this->creation_time;
+}
+
+METHOD(pts_ima_bios_list_t, get_count, int,
+	private_pts_ima_bios_list_t *this)
+{
+	return this->list->get_count(this->list);
+}
+
+METHOD(pts_ima_bios_list_t, get_next, status_t,
+	private_pts_ima_bios_list_t *this, uint32_t *pcr, chunk_t *measurement)
+{
+	bios_entry_t *entry;
+	status_t status;
+
+	status = this->list->remove_first(this->list, (void**)&entry);
+	*pcr = entry->pcr;
+	*measurement = entry->measurement;
+	free(entry);
+
+	return status;
+}
+
+METHOD(pts_ima_bios_list_t, destroy, void,
+	private_pts_ima_bios_list_t *this)
+{
+	this->list->destroy_function(this->list, (void *)free_bios_entry);
+	free(this);
+}
+
+/**
+ * See header
+ */
+pts_ima_bios_list_t* pts_ima_bios_list_create(char *file)
+{
+	private_pts_ima_bios_list_t *this;
+	uint32_t pcr, event_type, event_len, seek_len;
+	uint32_t buf_len = 2048;
+	uint8_t event_buf[buf_len];
+	chunk_t event;
+	bios_entry_t *entry;
+	struct stat st;
+	ssize_t res;
+	int fd;
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+	{
+		DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
+		return NULL;
+	}
+
+	if (fstat(fd, &st) == -1)
+	{
+		DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
+			 strerror(errno));
+		close(fd);
+		return FALSE;
+	}
+
+	INIT(this,
+		.public = {
+			.get_time = _get_time,
+			.get_count = _get_count,
+			.get_next = _get_next,
+			.destroy = _destroy,
+		},
+		.creation_time = st.st_ctime,
+		.list = linked_list_create(),
+	);
+
+	DBG2(DBG_PTS, "PCR Event Type  (Size)");
+	while (TRUE)
+	{
+		res = read(fd, &pcr, 4);
+		if (res == 0)
+		{
+			DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
+				 file, this->list->get_count(this->list));
+			close(fd);
+			return &this->public;
+		}
+
+		entry = malloc_thing(bios_entry_t);
+		entry->pcr = pcr;
+		entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
+
+		if (res != 4)
+		{
+			break;
+		}
+		if (read(fd, &event_type, 4) != 4)
+		{
+			break;
+		}
+		if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
+		{
+			break;
+		}
+		if (read(fd, &event_len, 4) != 4)
+		{
+			break;
+		}
+		DBG2(DBG_PTS, "%2u  %N  (%u bytes)", pcr, event_type_names, event_type,
+											 event_len);
+
+		seek_len = (event_len > buf_len) ? event_len - buf_len : 0;
+		event_len -= seek_len;
+
+		if (read(fd, event_buf, event_len) != event_len)
+		{
+			break;
+		}
+		event = chunk_create(event_buf, event_len);
+		DBG3(DBG_PTS,"%B", &event);
+
+		if (event_type == EV_ACTION || event_type == EV_EFI_ACTION)
+		{
+			DBG2(DBG_PTS, "     '%.*s'", event_len, event_buf);
+		}
+
+		if (seek_len > 0 && lseek(fd, seek_len, SEEK_CUR) == -1)
+		{
+				break;
+		}
+		this->list->insert_last(this->list, entry);
+	}
+
+	DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
+		 strerror(errno));
+	free_bios_entry(entry);
+	close(fd);
+	destroy(this);
+
+	return NULL;
+}
diff --git a/src/libpts/pts/pts_ima_bios_list.h b/src/libpts/pts/pts_ima_bios_list.h
new file mode 100644
index 0000000..ad162e1
--- /dev/null
+++ b/src/libpts/pts/pts_ima_bios_list.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 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 pts_ima_bios_list pts_ima_bios_list
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_IMA_BIOS_LIST_H_
+#define PTS_IMA_BIOS_LIST_H_
+
+#include <time.h>
+
+#include <library.h>
+
+typedef struct pts_ima_bios_list_t pts_ima_bios_list_t;
+
+/**
+ * Class retrieving Linux IMA BIOS measurements
+ *
+ */
+struct pts_ima_bios_list_t {
+
+	/**
+	 * Get the time the BIOS measurements were taken
+	 *
+	 * @return				Measurement time
+	 */
+	time_t (*get_time)(pts_ima_bios_list_t *this);
+
+	/**
+	 * Get the number of non-processed BIOS measurements
+	 *
+	 * @return				Number of measurements left
+	 */
+	int (*get_count)(pts_ima_bios_list_t *this);
+
+	/**
+	 * Get the next BIOS measurement and remove it from the list
+	 *
+	 * @param pcr			PCR where the measurement was extended into
+	 * @param measurement	Measurement hash
+	 * @return				Return code
+	 */
+	status_t (*get_next)(pts_ima_bios_list_t *this, uint32_t *pcr,
+													chunk_t *measurement);
+
+	/**
+	 * Destroys a pts_ima_bios_list_t object.
+	 */
+	void (*destroy)(pts_ima_bios_list_t *this);
+
+};
+
+/**
+ * Create a PTS IMA BIOS measurement object
+ *
+ * @param file				Pathname pointing to the BIOS measurements
+ */
+pts_ima_bios_list_t* pts_ima_bios_list_create(char *file);
+
+#endif /** PTS_IMA_BIOS_LIST_H_ @}*/
diff --git a/src/libpts/pts/pts_ima_event_list.c b/src/libpts/pts/pts_ima_event_list.c
new file mode 100644
index 0000000..9bff465
--- /dev/null
+++ b/src/libpts/pts/pts_ima_event_list.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2011-2014 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 "pts_ima_event_list.h"
+
+#include <utils/debug.h>
+#include <crypto/hashers/hasher.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+typedef struct private_pts_ima_event_list_t private_pts_ima_event_list_t;
+typedef struct event_entry_t event_entry_t;
+
+#define IMA_TYPE_LEN				3
+#define IMA_NG_TYPE_LEN				6
+#define IMA_TYPE_LEN_MAX			10
+#define IMA_ALGO_DIGEST_LEN_MAX		IMA_ALGO_LEN_MAX + HASH_SIZE_SHA512
+
+/**
+ * Private data of a pts_ima_event_list_t object.
+ *
+ */
+struct private_pts_ima_event_list_t {
+
+	/**
+	 * Public pts_ima_event_list_t interface.
+	 */
+	pts_ima_event_list_t public;
+
+	/**
+	 * List of BIOS measurement entries
+	 */
+	linked_list_t *list;
+
+	/**
+	 * Time when IMA runtime file measurements were taken
+	 */
+	time_t creation_time;
+
+};
+
+/**
+ * Linux IMA runtime file measurement entry
+ */
+struct event_entry_t {
+
+	/**
+	 * SHA1 measurement hash
+	 */
+	chunk_t measurement;
+
+	/**
+	 * IMA-NG hash algorithm name or NULL
+	 */
+	char *algo;
+
+	/**
+	 * IMA-NG eventname or IMA filename
+	 */
+	char *name;
+};
+
+/**
+ * Free an ima_event_t object
+ */
+static void free_event_entry(event_entry_t *this)
+{
+	free(this->measurement.ptr);
+	free(this->algo);
+	free(this->name);
+	free(this);
+}
+
+METHOD(pts_ima_event_list_t, get_time, time_t,
+	private_pts_ima_event_list_t *this)
+{
+	return this->creation_time;
+}
+
+METHOD(pts_ima_event_list_t, get_count, int,
+	private_pts_ima_event_list_t *this)
+{
+	return this->list->get_count(this->list);
+}
+
+METHOD(pts_ima_event_list_t, get_next, status_t,
+	private_pts_ima_event_list_t *this, chunk_t *measurement, char **algo,
+	char **name)
+{
+	event_entry_t *entry;
+	status_t status;
+
+	status = this->list->remove_first(this->list, (void**)&entry);
+	*measurement = entry->measurement;
+	*algo = entry->algo;
+	*name = entry->name;
+	free(entry);
+
+	return status;
+}
+
+METHOD(pts_ima_event_list_t, destroy, void,
+	private_pts_ima_event_list_t *this)
+{
+	this->list->destroy_function(this->list, (void *)free_event_entry);
+	free(this);
+}
+
+/**
+ * See header
+ */
+pts_ima_event_list_t* pts_ima_event_list_create(char *file)
+{
+	private_pts_ima_event_list_t *this;
+	event_entry_t *entry;
+	uint32_t pcr, type_len, name_len, eventdata_len, algo_digest_len, algo_len;
+	char type[IMA_TYPE_LEN_MAX];
+	char algo_digest[IMA_ALGO_DIGEST_LEN_MAX];
+	char *pos, *error = "";
+	struct stat st;
+	ssize_t res;
+	bool ima_ng;
+	int fd;
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+	{
+		DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
+		return NULL;
+	}
+
+	if (fstat(fd, &st) == -1)
+	{
+		DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
+			 strerror(errno));
+		close(fd);
+		return NULL;
+	}
+
+	INIT(this,
+		.public = {
+			.get_time = _get_time,
+			.get_count = _get_count,
+			.get_next = _get_next,
+			.destroy = _destroy,
+		},
+		.creation_time = st.st_ctime,
+		.list = linked_list_create(),
+	);
+
+	while (TRUE)
+	{
+		/* read 32 bit PCR number in host order */
+		res = read(fd, &pcr, 4);
+
+		/* exit if no more measurement data is available */
+		if (res == 0)
+		{
+			DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)",
+				 file, this->list->get_count(this->list));
+			close(fd);
+			return &this->public;
+		}
+
+		/* create and initialize new IMA entry */
+		entry = malloc_thing(event_entry_t);
+		entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
+		entry->algo = NULL;
+		entry->name = NULL;
+
+		if (res != 4 || pcr != IMA_PCR)
+		{
+			error = "invalid IMA PCR field";
+			break;
+		}
+
+		/* read 20 byte SHA-1 measurement digest */
+		if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
+		{
+			error = "invalid SHA-1 digest field";
+			break;
+		}
+
+		/* read 32 bit length of IMA type string in host order */
+		if (read(fd, &type_len, 4) != 4 || type_len > IMA_TYPE_LEN_MAX)
+		{
+			error = "invalid IMA type field length";
+			break;
+		}
+
+		/* read and interpret IMA type string */
+		if (read(fd, type, type_len) != type_len)
+		{
+			error = "invalid IMA type field";
+			break;
+		}
+		if (type_len == IMA_NG_TYPE_LEN &&
+			memeq(type, "ima-ng", IMA_NG_TYPE_LEN))
+		{
+			ima_ng = TRUE;
+		}
+		else if (type_len == IMA_TYPE_LEN &&
+				 memeq(type, "ima", IMA_TYPE_LEN))
+		{
+			ima_ng = FALSE;
+		}
+		else
+		{
+			error = "unknown IMA type";
+			break;
+		}
+
+		if (ima_ng)
+		{
+			/* read the 32 bit length of the event data in host order */
+			if (read(fd, &eventdata_len, 4) != 4 || eventdata_len < 4)
+			{
+				error = "invalid event data field length";
+				break;
+			}
+
+			/* read the 32 bit length of the algo_digest string in host order */
+			if (read(fd, &algo_digest_len, 4) != 4 ||
+				algo_digest_len > IMA_ALGO_DIGEST_LEN_MAX ||
+				eventdata_len < 4 + algo_digest_len + 4)
+			{
+				error = "invalid digest_with_algo field length";
+				break;
+			}
+
+			/* read the IMA algo_digest string */
+			if (read(fd, algo_digest, algo_digest_len) != algo_digest_len)
+			{
+				error = "invalid digest_with_algo field";
+				break;
+			}
+
+			/* extract the hash algorithm name */
+			pos = memchr(algo_digest, '\0', algo_digest_len);
+			if (!pos)
+			{
+				error = "no algo field";
+				break;
+			}
+			algo_len = pos - algo_digest + 1;
+
+			if (algo_len > IMA_ALGO_LEN_MAX ||
+				algo_len < IMA_ALGO_LEN_MIN || *(pos - 1) != ':')
+			{
+				error = "invalid algo field";
+				break;
+			}
+
+			/* copy and store the hash algorithm name */
+			entry->algo = malloc(algo_len);
+			memcpy(entry->algo, algo_digest, algo_len);
+
+			/* read the 32 bit length of the event name in host order */
+			if (read(fd, &name_len, 4) != 4 ||
+				eventdata_len != 4 + algo_digest_len + 4 + name_len)
+			{
+				error = "invalid filename field length";
+				break;
+			}
+
+			/* allocate memory for the file name */
+			entry->name = malloc(name_len);
+
+			/* read file name */
+			if (read(fd, entry->name, name_len) != name_len)
+			{
+				error = "invalid filename field";
+				break;
+			}
+		}
+		else
+		{
+			/* skip SHA-1 digest of the file content */
+			if (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1)
+			{
+				break;
+			}
+
+			/* read the 32 bit length of the file name in host order */
+			if (read(fd, &name_len, 4) != 4 || name_len == UINT32_MAX)
+			{
+				error = "invalid filename field length";
+				break;
+			}
+
+			/* allocate memory for the file name */
+			entry->name = malloc(name_len + 1);
+
+			/* read file name */
+			if (read(fd, entry->name, name_len) != name_len)
+			{
+				error = "invalid eventname field";
+				break;
+			}
+
+			/* terminate the file name with a nul character */
+			entry->name[name_len] = '\0';
+		}
+
+		this->list->insert_last(this->list, entry);
+	}
+
+	DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s", file, error);
+	free_event_entry(entry);
+	close(fd);
+	destroy(this);
+
+	return NULL;
+}
diff --git a/src/libpts/pts/pts_ima_event_list.h b/src/libpts/pts/pts_ima_event_list.h
new file mode 100644
index 0000000..bf5478a
--- /dev/null
+++ b/src/libpts/pts/pts_ima_event_list.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 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 pts_ima_event_list pts_ima_event_list
+ * @{ @ingroup pts
+ */
+
+#ifndef PTS_IMA_EVENT_LIST_H_
+#define PTS_IMA_EVENT_LIST_H_
+
+#include <time.h>
+
+#include <library.h>
+
+typedef struct pts_ima_event_list_t pts_ima_event_list_t;
+
+#define IMA_PCR				10
+#define IMA_ALGO_LEN_MIN	5
+#define IMA_ALGO_LEN_MAX	8
+
+
+/**
+ * Class retrieving Linux IMA file measurements
+ *
+ */
+struct pts_ima_event_list_t {
+
+	/**
+	 * Get the time the file measurements were taken
+	 *
+	 * @return				Measurement time
+	 */
+	time_t (*get_time)(pts_ima_event_list_t *this);
+
+	/**
+	 * Get the number of non-processed file measurements
+	 *
+	 * @return				Number of measurements left
+	 */
+	int (*get_count)(pts_ima_event_list_t *this);
+
+	/**
+	 * Get the next file measurement and remove it from the list
+	 *
+	 * @param measurement	Measurement hash
+	 * @param algo			Algorithm used to hash files
+	 " @param name			Event name (absolute filename or boot_aggregate) 
+	 * @return				Return code
+	 */
+	status_t (*get_next)(pts_ima_event_list_t *this, chunk_t *measurement,
+						 char **algo, char **name);
+
+	/**
+	 * Destroys a pts_ima_event_list_t object.
+	 */
+	void (*destroy)(pts_ima_event_list_t *this);
+
+};
+
+/**
+ * Create a PTS IMA runtime file measurement object
+ *
+ * @param file				Pathname pointing to the IMA runtme measurements
+ */
+pts_ima_event_list_t* pts_ima_event_list_create(char *file);
+
+#endif /** PTS_IMA_EVENT_LIST_H_ @}*/
diff --git a/src/libpts/pts/pts_meas_algo.c b/src/libpts/pts/pts_meas_algo.c
index 16a66e7..c063711 100644
--- a/src/libpts/pts/pts_meas_algo.c
+++ b/src/libpts/pts/pts_meas_algo.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -28,10 +28,7 @@ ENUM_NEXT(pts_meas_algorithm_names,	PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256,
 ENUM_NEXT(pts_meas_algorithm_names,	PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA1,
 									PTS_MEAS_ALGO_SHA256,
 	"SHA1");
-ENUM_NEXT(pts_meas_algorithm_names,	PTS_MEAS_ALGO_SHA1_IMA, PTS_MEAS_ALGO_SHA1_IMA,
-									PTS_MEAS_ALGO_SHA1,
-	"SHA1-IMA");
-ENUM_END(pts_meas_algorithm_names,  PTS_MEAS_ALGO_SHA1_IMA);
+ENUM_END(pts_meas_algorithm_names,  PTS_MEAS_ALGO_SHA1);
 
 /**
  * Described in header.
diff --git a/src/libpts/pts/pts_meas_algo.h b/src/libpts/pts/pts_meas_algo.h
index 27cdaea..eec7e79 100644
--- a/src/libpts/pts/pts_meas_algo.h
+++ b/src/libpts/pts/pts_meas_algo.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Sansar Choinyambuu
+ * Copyright (C) 2011-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -33,8 +34,7 @@ enum pts_meas_algorithms_t {
 	PTS_MEAS_ALGO_NONE     =      0,
 	PTS_MEAS_ALGO_SHA384   = (1<<13),
 	PTS_MEAS_ALGO_SHA256   = (1<<14),
-	PTS_MEAS_ALGO_SHA1     = (1<<15),
-	PTS_MEAS_ALGO_SHA1_IMA = (1<<16), /* internal use only */
+	PTS_MEAS_ALGO_SHA1     = (1<<15)
 };
 
 /**
diff --git a/src/libpts/swid/swid_error.c b/src/libpts/swid/swid_error.c
index 7f7da76..7f3c344 100644
--- a/src/libpts/swid/swid_error.c
+++ b/src/libpts/swid/swid_error.c
@@ -40,7 +40,7 @@ pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request_id,
 	writer->write_uint32(writer, request_id);
 	if (code == TCG_SWID_RESPONSE_TOO_LARGE)
 	{
-		writer->write_uint16(writer, max_attr_size);
+		writer->write_uint32(writer, max_attr_size);
 	}
 	if (description)
 	{
diff --git a/src/libpts/swid/swid_inventory.c b/src/libpts/swid/swid_inventory.c
index a71682f..a9f081e 100644
--- a/src/libpts/swid/swid_inventory.c
+++ b/src/libpts/swid/swid_inventory.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
 #include "swid_tag_id.h"
 
 #include <collections/linked_list.h>
+#include <bio/bio_writer.h>
 #include <utils/debug.h>
 
 #include <stdio.h>
@@ -51,6 +52,194 @@ struct private_swid_inventory_t {
 	linked_list_t *list;
 };
 
+/**
+ * Read SWID tags issued by the swid_generator tool
+ */
+static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file)
+{
+	swid_tag_t *tag;
+	bio_writer_t *writer;
+	chunk_t tag_encoding, tag_file_path = chunk_empty;
+	bool more_tags = TRUE, last_newline, end_of_tag;
+	char line[8192];
+	size_t len;
+
+	while (more_tags)
+	{
+		last_newline = TRUE;
+		end_of_tag = FALSE;
+		writer = bio_writer_create(512);
+		do
+		{
+			if (!fgets(line, sizeof(line), file))
+			{
+				more_tags = FALSE;
+				end_of_tag = TRUE;
+				break;
+			}
+			len = strlen(line);
+
+			if (last_newline && line[0] == '\n')
+			{
+				end_of_tag = TRUE;
+				break;
+			}
+			else
+			{
+				last_newline = (line[len-1] == '\n');
+				writer->write_data(writer, chunk_create(line, len));
+			}
+		}
+		while (!end_of_tag);
+
+		tag_encoding = writer->get_buf(writer);
+
+		if (tag_encoding.len > 1)
+		{
+			/* remove trailing newline if present */
+			if (tag_encoding.ptr[tag_encoding.len - 1] == '\n')
+			{
+				tag_encoding.len--;
+			}
+			DBG3(DBG_IMC, "  %.*s", tag_encoding.len, tag_encoding.ptr);
+
+			tag = swid_tag_create(tag_encoding, tag_file_path);
+			this->list->insert_last(this->list, tag);
+		}
+		writer->destroy(writer);
+	}
+
+	return SUCCESS;
+}
+
+/**
+ * Read SWID tag or software IDs issued by the swid_generator tool
+ */
+static status_t read_swid_tag_ids(private_swid_inventory_t *this, FILE *file)
+{
+	swid_tag_id_t *tag_id;
+	chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty;
+	char line[BUF_LEN];
+
+	while (TRUE)
+	{
+		char *separator;
+		size_t len;
+
+		if (!fgets(line, sizeof(line), file))
+		{
+			return SUCCESS;
+		}
+		len = strlen(line);
+
+		/* remove trailing newline if present */
+		if (len > 0 && line[len - 1] == '\n')
+		{
+			len--;
+		}
+		DBG3(DBG_IMC, "  %.*s", len, line);
+
+		separator = strchr(line, '_');
+		if (!separator)
+		{
+			DBG1(DBG_IMC, "separation of regid from unique software ID failed");
+			return FAILED;
+		}
+		tag_creator = chunk_create(line, separator - line);
+		separator++;
+
+		unique_sw_id = chunk_create(separator, len - (separator - line));
+		tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
+		this->list->insert_last(this->list, tag_id);
+	}
+}
+
+static status_t generate_tags(private_swid_inventory_t *this, char *generator,
+							  swid_inventory_t *targets, bool pretty, bool full)
+{
+	FILE *file;
+	char command[BUF_LEN];
+	char doc_separator[] = "'\n\n'";
+
+	status_t status = SUCCESS;
+
+	if (targets->get_count(targets) == 0)
+	{
+		/* Assemble the SWID generator command */
+		if (this->full_tags)
+		{
+			snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s",
+					 generator, doc_separator, pretty ? " --pretty" : "",
+											   full   ? " --full"   : "");
+		}
+		else
+		{
+			snprintf(command, BUF_LEN, "%s software-id", generator);
+		}
+
+		/* Open a pipe stream for reading the SWID generator output */
+		file = popen(command, "r");
+		if (!file)
+		{
+			DBG1(DBG_IMC, "failed to run swid_generator command");
+			return NOT_SUPPORTED;
+		}
+
+		if (this->full_tags)
+		{
+			DBG2(DBG_IMC, "SWID tag generation by package manager");
+			status = read_swid_tags(this, file);
+		}
+		else
+		{
+			DBG2(DBG_IMC, "SWID tag ID generation by package manager");
+			status = read_swid_tag_ids(this, file);
+		}
+		pclose(file);
+	}
+	else if (this->full_tags)
+	{
+		swid_tag_id_t *tag_id;
+		enumerator_t *enumerator;
+
+		enumerator = targets->create_enumerator(targets);
+		while (enumerator->enumerate(enumerator, &tag_id))
+		{
+			char software_id[BUF_LEN];
+			chunk_t tag_creator, unique_sw_id;
+
+			tag_creator  = tag_id->get_tag_creator(tag_id);
+			unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+			snprintf(software_id, BUF_LEN, "%.*s_%.*s",
+					 tag_creator.len, tag_creator.ptr,
+					 unique_sw_id.len, unique_sw_id.ptr);
+
+			/* Assemble the SWID generator command */
+			snprintf(command, BUF_LEN, "%s swid --software-id %s%s%s",
+					 generator, software_id, pretty ? " --pretty" : "",
+											 full   ? " --full"   : "");
+
+			/* Open a pipe stream for reading the SWID generator output */
+			file = popen(command, "r");
+			if (!file)
+			{
+				DBG1(DBG_IMC, "failed to run swid_generator command");
+				return NOT_SUPPORTED;
+			}
+			status = read_swid_tags(this, file);
+			pclose(file);
+
+			if (status != SUCCESS)
+			{
+				break;
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+
+	return status;
+}
+
 static bool collect_tags(private_swid_inventory_t *this, char *pathname,
 						 swid_inventory_t *targets)
 {
@@ -72,7 +261,8 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
 	{
 		char * start, *stop;
 		chunk_t tag_creator;
-		chunk_t unique_sw_id = chunk_empty, unique_seq_id = chunk_empty;
+		chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty;
+
 		if (!strstr(rel_name, "regid."))
 		{
 			continue;
@@ -121,14 +311,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
 			goto end;
 		}
 		tag_creator = chunk_create(start, stop-start);
-
 		start = stop + 1;
-		stop = strchr(start, '_');
-		if (stop)
-		{
-			unique_sw_id = chunk_create(start, stop-start);
-			start = stop + 1;
-		}
 
 		stop = strstr(start, ".swidtag");
 		if (!stop)
@@ -137,18 +320,13 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
 			DBG1(DBG_IMC, "  swidtag postfix not found");
 			goto end;
 		}
-		if (unique_sw_id.ptr)
-		{
-			unique_seq_id = chunk_create(start, stop-start);
-		}
-		else
-		{
-			unique_sw_id = chunk_create(start, stop-start);
-		}
+		unique_sw_id = chunk_create(start, stop-start);
+		tag_file_path = chunk_from_str(abs_name);
 
 		/* In case of a targeted request */
 		if (targets->get_count(targets))
 		{
+			chunk_t target_unique_sw_id, target_tag_creator;
 			enumerator_t *target_enumerator;
 			swid_tag_id_t *tag_id;
 			bool match = FALSE;
@@ -156,10 +334,11 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
 			target_enumerator = targets->create_enumerator(targets);
 			while (target_enumerator->enumerate(target_enumerator, &tag_id))
 			{
-				if (chunk_equals(tag_id->get_unique_sw_id(tag_id, NULL),
-								 unique_sw_id) &&
-					chunk_equals(tag_id->get_tag_creator(tag_id),
-								 tag_creator))
+				target_unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+				target_tag_creator  = tag_id->get_tag_creator(tag_id);
+
+				if (chunk_equals(target_unique_sw_id, unique_sw_id) &&
+					chunk_equals(target_tag_creator, tag_creator))
 				{
 					match = TRUE;
 					break;
@@ -187,7 +366,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
 				goto end;
 			}
 
-			tag = swid_tag_create(*xml_tag, unique_seq_id);
+			tag = swid_tag_create(*xml_tag, tag_file_path);
 			this->list->insert_last(this->list, tag);
 			chunk_unmap(xml_tag);
 		}
@@ -195,10 +374,9 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
 		{
 			swid_tag_id_t *tag_id;
 
-			tag_id = swid_tag_id_create(tag_creator, unique_sw_id, unique_seq_id);
+			tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
 			this->list->insert_last(this->list, tag_id);
 		}
-
 	}
 	success = TRUE;
 
@@ -210,8 +388,18 @@ end:
 }
 
 METHOD(swid_inventory_t, collect, bool,
-	private_swid_inventory_t *this, char *directory, swid_inventory_t *targets)
+	private_swid_inventory_t *this, char *directory, char *generator,
+	swid_inventory_t *targets, bool pretty, bool full)
 {
+	/**
+	 * Tags are generated by a package manager
+	 */
+	generate_tags(this, generator, targets, pretty, full);
+
+	/**
+	 * Collect swidtag files by iteratively entering all directories in
+	 * the tree under the "directory" path.
+	 */
 	return collect_tags(this, directory, targets);
 }
 
diff --git a/src/libpts/swid/swid_inventory.h b/src/libpts/swid/swid_inventory.h
index 68d3047..7de8bb2 100644
--- a/src/libpts/swid/swid_inventory.h
+++ b/src/libpts/swid/swid_inventory.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -34,11 +34,14 @@ struct swid_inventory_t {
 	 * Collect the SWID tags stored on the endpoint
 	 *
 	 * @param directory		SWID directory path
+	 * @param generator		Path to SWID generator
 	 * @param targets		List of target tag IDs
+	 * @param pretty		Generate indented XML SWID tags
+	 * @param full			Include file information in SWID tags
 	 * @return				TRUE if successful
 	 */
-	bool (*collect)(swid_inventory_t *this, char *directory,
-					swid_inventory_t *targets);
+	bool (*collect)(swid_inventory_t *this, char *directory, char *generator,
+					swid_inventory_t *targets, bool pretty, bool full);
 
 	/**
 	 * Collect the SWID tags stored on the endpoint
diff --git a/src/libpts/swid/swid_tag.c b/src/libpts/swid/swid_tag.c
index 0b65196..c71d5d2 100644
--- a/src/libpts/swid/swid_tag.c
+++ b/src/libpts/swid/swid_tag.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -34,10 +34,14 @@ struct private_swid_tag_t {
 	chunk_t encoding;
 
 	/**
-	 * Optional Unique Sequence ID
+	 * Optional Tag File Path
 	 */
-	chunk_t unique_seq_id;
+	chunk_t tag_file_path;
 
+	/**
+	 * Reference count
+	 */
+	refcount_t ref;
 };
 
 METHOD(swid_tag_t, get_encoding, chunk_t,
@@ -46,39 +50,51 @@ METHOD(swid_tag_t, get_encoding, chunk_t,
 	return this->encoding;
 }
 
-METHOD(swid_tag_t, get_unique_seq_id, chunk_t,
+METHOD(swid_tag_t, get_tag_file_path, chunk_t,
 	private_swid_tag_t *this)
 {
-	return this->unique_seq_id;
+	return this->tag_file_path;
+}
+
+METHOD(swid_tag_t, get_ref, swid_tag_t*,
+	private_swid_tag_t *this)
+{
+	ref_get(&this->ref);
+	return &this->public;
 }
 
 METHOD(swid_tag_t, destroy, void,
 	private_swid_tag_t *this)
 {
-	free(this->encoding.ptr);
-	free(this->unique_seq_id.ptr);
-	free(this);
+	if (ref_put(&this->ref))
+	{
+		free(this->encoding.ptr);
+		free(this->tag_file_path.ptr);
+		free(this);
+	}
 }
 
 /**
  * See header
  */
-swid_tag_t *swid_tag_create(chunk_t encoding, chunk_t unique_seq_id)
+swid_tag_t *swid_tag_create(chunk_t encoding, chunk_t tag_file_path)
 {
 	private_swid_tag_t *this;
 
 	INIT(this,
 		.public = {
 			.get_encoding = _get_encoding,
-			.get_unique_seq_id = _get_unique_seq_id,
+			.get_tag_file_path = _get_tag_file_path,
+			.get_ref = _get_ref,
 			.destroy = _destroy,
 		},
 		.encoding = chunk_clone(encoding),
+		.ref = 1,
 	);
 
-	if (unique_seq_id.len > 0)
+	if (tag_file_path.len > 0)
 	{
-		this->unique_seq_id = chunk_clone(unique_seq_id);
+		this->tag_file_path = chunk_clone(tag_file_path);
 	}
 
 	return &this->public;
diff --git a/src/libpts/swid/swid_tag.h b/src/libpts/swid/swid_tag.h
index 9d3f863..e20c538 100644
--- a/src/libpts/swid/swid_tag.h
+++ b/src/libpts/swid/swid_tag.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -39,11 +39,18 @@ struct swid_tag_t {
 	chunk_t (*get_encoding)(swid_tag_t *this);
 
 	/**
-	 * Get th Optional Unique Sequence ID
+	 * Get th Optional Tag File Path
 	 *
-	 * @return				Optional Unique Sequence ID
+	 * @return				Optional Tag File Path
 	 */
-	chunk_t (*get_unique_seq_id)(swid_tag_t *this);
+	chunk_t (*get_tag_file_path)(swid_tag_t *this);
+
+	/**
+	 * Get a new reference to the swid_tag object
+	 *
+	 * @return			this, with an increased refcount
+	 */
+	swid_tag_t* (*get_ref)(swid_tag_t *this);
 
 	/**
 	 * Destroys a swid_tag_t object.
@@ -56,8 +63,8 @@ struct swid_tag_t {
  * Creates a swid_tag_t object
  *
  * @param encoding			XML encoding of SWID tag
- * @param unique_seq_id		Unique Sequence ID or empty chunk 
+ * @param tag_file_path		Tag File Path or empty chunk
  */
-swid_tag_t* swid_tag_create(chunk_t encoding, chunk_t unique_seq_id);
+swid_tag_t* swid_tag_create(chunk_t encoding, chunk_t tag_file_path);
 
 #endif /** SWID_TAG_H_ @}*/
diff --git a/src/libpts/swid/swid_tag_id.c b/src/libpts/swid/swid_tag_id.c
index 7ad486d..8bede28 100644
--- a/src/libpts/swid/swid_tag_id.c
+++ b/src/libpts/swid/swid_tag_id.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -39,10 +39,14 @@ struct private_swid_tag_id_t {
 	chunk_t unique_sw_id;
 
 	/**
-	 * Optional Unique Sequence ID
+	 * Tag File Path
 	 */
-	chunk_t unique_seq_id;
+	chunk_t tag_file_path;
 
+	/**
+	 * Reference count
+	 */
+	refcount_t ref;
 };
 
 METHOD(swid_tag_id_t, get_tag_creator, chunk_t,
@@ -52,29 +56,39 @@ METHOD(swid_tag_id_t, get_tag_creator, chunk_t,
 }
 
 METHOD(swid_tag_id_t, get_unique_sw_id, chunk_t,
-	private_swid_tag_id_t *this, chunk_t *unique_seq_id)
+	private_swid_tag_id_t *this, chunk_t *tag_file_path)
 {
-	if (unique_seq_id)
+	if (tag_file_path)
 	{
-		*unique_seq_id = this->unique_seq_id;
+		*tag_file_path = this->tag_file_path;
 	}
 	return this->unique_sw_id;
 }
 
+METHOD(swid_tag_id_t, get_ref, swid_tag_id_t*,
+	private_swid_tag_id_t *this)
+{
+	ref_get(&this->ref);
+	return &this->public;
+}
+
 METHOD(swid_tag_id_t, destroy, void,
 	private_swid_tag_id_t *this)
 {
-	free(this->tag_creator.ptr);
-	free(this->unique_sw_id.ptr);
-	free(this->unique_seq_id.ptr);
-	free(this);
+	if (ref_put(&this->ref))
+	{
+		free(this->tag_creator.ptr);
+		free(this->unique_sw_id.ptr);
+		free(this->tag_file_path.ptr);
+		free(this);
+	}
 }
 
 /**
  * See header
  */
 swid_tag_id_t *swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
-								  chunk_t unique_seq_id)
+								  chunk_t tag_file_path)
 {
 	private_swid_tag_id_t *this;
 
@@ -82,15 +96,17 @@ swid_tag_id_t *swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
 		.public = {
 			.get_tag_creator = _get_tag_creator,
 			.get_unique_sw_id = _get_unique_sw_id,
+			.get_ref = _get_ref,
 			.destroy = _destroy,
 		},
 		.tag_creator = chunk_clone(tag_creator),
 		.unique_sw_id = chunk_clone(unique_sw_id),
+		.ref = 1,
 	);
 
-	if (unique_seq_id.len > 0)
+	if (tag_file_path.len > 0)
 	{
-		this->unique_seq_id = chunk_clone(unique_seq_id);
+		this->tag_file_path = chunk_clone(tag_file_path);
 	}
 
 	return &this->public;
diff --git a/src/libpts/swid/swid_tag_id.h b/src/libpts/swid/swid_tag_id.h
index d471596..d2a783b 100644
--- a/src/libpts/swid/swid_tag_id.h
+++ b/src/libpts/swid/swid_tag_id.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -39,12 +39,19 @@ struct swid_tag_id_t {
 	chunk_t (*get_tag_creator)(swid_tag_id_t *this);
 
 	/**
-	 * Get the Unique Software ID and optional Unique Sequence ID
+	 * Get the Unique Software ID and optional Tag File Path
 	 *
-	 * @param				Optional Unique Sequence ID
+	 * @param				Optional Tag File Path
 	 * @return				Unique Software ID
 	 */
-	chunk_t (*get_unique_sw_id)(swid_tag_id_t *this, chunk_t *unique_seq_id);
+	chunk_t (*get_unique_sw_id)(swid_tag_id_t *this, chunk_t *tag_file_path);
+
+	/**
+	 * Get a new reference to the swid_tag_id object
+	 *
+	 * @return			this, with an increased refcount
+	 */
+	swid_tag_id_t* (*get_ref)(swid_tag_id_t *this);
 
 	/**
 	 * Destroys a swid_tag_id_t object.
@@ -58,9 +65,9 @@ struct swid_tag_id_t {
  *
  * @param tag_creator		Tag Creator
  * @param unique_sw_id		Unique Software ID
- * @param unique_seq_id		Unique Sequence ID or empty chunk 
+ * @param tag_file_path		Tag File Path or empty chunk
  */
 swid_tag_id_t* swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
-								  chunk_t unique_seq_id);
+								  chunk_t tag_file_path);
 
 #endif /** SWID_TAG_ID_H_ @}*/
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_req.c b/src/libpts/tcg/swid/tcg_swid_attr_req.c
index b8e7962..c403d06 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_req.c
+++ b/src/libpts/tcg/swid/tcg_swid_attr_req.c
@@ -44,7 +44,6 @@ typedef struct private_tcg_swid_attr_req_t private_tcg_swid_attr_req_t;
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
-#define SWID_REQ_SIZE					12
 #define SWID_REQ_RESERVED_MASK			0x03
 
 /**
@@ -135,7 +134,7 @@ METHOD(pa_tnc_attr_t, build, void,
 		return;
 	}
 
-	writer = bio_writer_create(SWID_REQ_SIZE);
+	writer = bio_writer_create(TCG_SWID_REQ_MIN_SIZE);
 	writer->write_uint8 (writer, this->flags);
 	writer->write_uint24(writer, this->targets->get_count(this->targets));
 	writer->write_uint32(writer, this->request_id);
@@ -163,7 +162,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
 	chunk_t tag_creator, unique_sw_id;
 	swid_tag_id_t *tag_id;
 
-	if (this->value.len < SWID_REQ_SIZE)
+	if (this->value.len < TCG_SWID_REQ_MIN_SIZE)
 	{
 		DBG1(DBG_TNC, "insufficient data for SWID Request");
 		*offset = 0;
@@ -181,7 +180,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
 		*offset = 4;
 		return FAILED;
 	}
-	*offset = SWID_REQ_SIZE;
+	*offset = TCG_SWID_REQ_MIN_SIZE;
 
 	this->flags &= SWID_REQ_RESERVED_MASK;
 
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_req.h b/src/libpts/tcg/swid/tcg_swid_attr_req.h
index 851b68d..59b597d 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_req.h
+++ b/src/libpts/tcg/swid/tcg_swid_attr_req.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -21,6 +21,8 @@
 #ifndef TCG_SWID_ATTR_REQ_H_
 #define TCG_SWID_ATTR_REQ_H_
 
+#define TCG_SWID_REQ_MIN_SIZE	12
+
 typedef struct tcg_swid_attr_req_t tcg_swid_attr_req_t;
 typedef enum tcg_swid_attr_req_flag_t tcg_swid_attr_req_flag_t;
 
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c
index 429919e..33aa16d 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -42,12 +42,11 @@ typedef struct private_tcg_swid_attr_tag_id_inv_t private_tcg_swid_attr_tag_id_i
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *  |    Unique Software ID Length  |Unique Software ID (var length)|
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *  |   Unique Sequence ID Length   |Unique Sequence ID (var length)|
+ *  |      Tag File Path Length     |  Tag File Path (var. length)  |
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
-#define SWID_TAG_ID_INV_SIZE			16
-#define SWID_TAG_ID_INV_RESERVED		0x00
+#define TCG_SWID_TAG_ID_INV_RESERVED	0x00
 
 /**
  * Private data of an tcg_swid_attr_tag_id_inv_t object.
@@ -77,17 +76,17 @@ struct private_tcg_swid_attr_tag_id_inv_t {
 	/**
 	 * Request ID
 	 */
-	u_int32_t request_id;
+	uint32_t request_id;
 
 	/**
 	 * Event ID Epoch
 	 */
-	u_int32_t eid_epoch;
+	uint32_t eid_epoch;
 
 	/**
 	 * Last Event ID
 	 */
-	u_int32_t last_eid;
+	uint32_t last_eid;
 
 	/**
 	 * SWID Tag ID Inventory
@@ -129,7 +128,7 @@ METHOD(pa_tnc_attr_t, build, void,
 {
 	bio_writer_t *writer;
 	swid_tag_id_t *tag_id;
-	chunk_t tag_creator, unique_sw_id, unique_seq_id;
+	chunk_t tag_creator, unique_sw_id, tag_file_path;
 	enumerator_t *enumerator;
 
 	if (this->value.ptr)
@@ -137,8 +136,8 @@ METHOD(pa_tnc_attr_t, build, void,
 		return;
 	}
 
-	writer = bio_writer_create(SWID_TAG_ID_INV_SIZE);
-	writer->write_uint8 (writer, SWID_TAG_ID_INV_RESERVED);
+	writer = bio_writer_create(TCG_SWID_TAG_ID_INV_MIN_SIZE);
+	writer->write_uint8 (writer, TCG_SWID_TAG_ID_INV_RESERVED);
 	writer->write_uint24(writer, this->inventory->get_count(this->inventory));
 	writer->write_uint32(writer, this->request_id);
 	writer->write_uint32(writer, this->eid_epoch);
@@ -148,10 +147,10 @@ METHOD(pa_tnc_attr_t, build, void,
 	while (enumerator->enumerate(enumerator, &tag_id))
 	{
 		tag_creator = tag_id->get_tag_creator(tag_id);
-		unique_sw_id = tag_id->get_unique_sw_id(tag_id, &unique_seq_id);
+		unique_sw_id = tag_id->get_unique_sw_id(tag_id, &tag_file_path);
 		writer->write_data16(writer, tag_creator);
 		writer->write_data16(writer, unique_sw_id);
-		writer->write_data16(writer, unique_seq_id);
+		writer->write_data16(writer, tag_file_path);
 	}
 	enumerator->destroy(enumerator);
 
@@ -160,15 +159,15 @@ METHOD(pa_tnc_attr_t, build, void,
 }
 
 METHOD(pa_tnc_attr_t, process, status_t,
-	private_tcg_swid_attr_tag_id_inv_t *this, u_int32_t *offset)
+	private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *offset)
 {
 	bio_reader_t *reader;
-	u_int32_t tag_id_count;
-	u_int8_t reserved;
-	chunk_t tag_creator, unique_sw_id, unique_seq_id;
+	uint32_t tag_id_count;
+	uint8_t reserved;
+	chunk_t tag_creator, unique_sw_id, tag_file_path;
 	swid_tag_id_t *tag_id;
 
-	if (this->value.len < SWID_TAG_ID_INV_SIZE)
+	if (this->value.len < TCG_SWID_TAG_ID_INV_MIN_SIZE)
 	{
 		DBG1(DBG_TNC, "insufficient data for SWID Tag Identifier Inventory");
 		*offset = 0;
@@ -181,7 +180,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
 	reader->read_uint32(reader, &this->request_id);
 	reader->read_uint32(reader, &this->eid_epoch);
 	reader->read_uint32(reader, &this->last_eid);
-	*offset = SWID_TAG_ID_INV_SIZE;
+	*offset = TCG_SWID_TAG_ID_INV_MIN_SIZE;
 
 	while (tag_id_count--)
 	{
@@ -199,14 +198,14 @@ METHOD(pa_tnc_attr_t, process, status_t,
 		}
 		*offset += 2 + unique_sw_id.len;
 		
-		if (!reader->read_data16(reader, &unique_seq_id))
+		if (!reader->read_data16(reader, &tag_file_path))
 		{
-			DBG1(DBG_TNC, "insufficient data for Unique Sequence ID");
+			DBG1(DBG_TNC, "insufficient data for Tag File Path");
 			return FAILED;
 		}
-		*offset += 2 + unique_seq_id.len;
+		*offset += 2 + tag_file_path.len;
 
-		tag_id = swid_tag_id_create(tag_creator, unique_sw_id, unique_seq_id);
+		tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
 		this->inventory->add(this->inventory, tag_id);
 	}
 	reader->destroy(reader);
@@ -232,14 +231,20 @@ METHOD(pa_tnc_attr_t, destroy, void,
 	}
 }
 
-METHOD(tcg_swid_attr_tag_id_inv_t, get_request_id, u_int32_t,
+METHOD(tcg_swid_attr_tag_id_inv_t, add, void,
+	private_tcg_swid_attr_tag_id_inv_t *this, swid_tag_id_t *tag_id)
+{
+	this->inventory->add(this->inventory, tag_id);
+}
+
+METHOD(tcg_swid_attr_tag_id_inv_t, get_request_id, uint32_t,
 	private_tcg_swid_attr_tag_id_inv_t *this)
 {
 	return this->request_id;
 }
 
-METHOD(tcg_swid_attr_tag_id_inv_t, get_last_eid, u_int32_t,
-	private_tcg_swid_attr_tag_id_inv_t *this, u_int32_t *eid_epoch)
+METHOD(tcg_swid_attr_tag_id_inv_t, get_last_eid, uint32_t,
+	private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *eid_epoch)
 {
 	if (eid_epoch)
 	{
@@ -257,10 +262,9 @@ METHOD(tcg_swid_attr_tag_id_inv_t, get_inventory, swid_inventory_t*,
 /**
  * Described in header.
  */
-pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
-											   u_int32_t eid_epoch,
-											   u_int32_t eid,
-											   swid_inventory_t *inventory)
+pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(uint32_t request_id,
+											   uint32_t eid_epoch,
+											   uint32_t eid)
 {
 	private_tcg_swid_attr_tag_id_inv_t *this;
 
@@ -276,6 +280,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
 				.get_ref = _get_ref,
 				.destroy = _destroy,
 			},
+			.add = _add,
 			.get_request_id = _get_request_id,
 			.get_last_eid = _get_last_eid,
 			.get_inventory = _get_inventory,
@@ -284,7 +289,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
 		.request_id = request_id,
 		.eid_epoch = eid_epoch,
 		.last_eid = eid,
-		.inventory = inventory,
+		.inventory = swid_inventory_create(FALSE),
 		.ref = 1,
 	);
 
@@ -311,6 +316,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create_from_data(chunk_t data)
 				.get_ref = _get_ref,
 				.destroy = _destroy,
 			},
+			.add = _add,
 			.get_request_id = _get_request_id,
 			.get_last_eid = _get_last_eid,
 			.get_inventory = _get_inventory,
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h
index 1a0cbe7..c4ade90 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@ typedef struct tcg_swid_attr_tag_id_inv_t tcg_swid_attr_tag_id_inv_t;
 
 #include <pa_tnc/pa_tnc_attr.h>
 
+#define TCG_SWID_TAG_ID_INV_MIN_SIZE	16
+
 /**
  * Class implementing the TCG SWID Tag Identifier Inventory attribute
  *
@@ -41,11 +43,18 @@ struct tcg_swid_attr_tag_id_inv_t {
 	pa_tnc_attr_t pa_tnc_attribute;
 
 	/**
+	 * Add a Tag ID to the attribute
+	 *
+	 * @param tag_id			SWID Tag ID to be added
+	 */
+	void (*add)(tcg_swid_attr_tag_id_inv_t *this, swid_tag_id_t *tag_id);
+
+	/**
 	 * Get Request ID
 	 *
 	 * @return					Request ID
 	 */
-	u_int32_t (*get_request_id)(tcg_swid_attr_tag_id_inv_t *this);
+	uint32_t (*get_request_id)(tcg_swid_attr_tag_id_inv_t *this);
 
 	/**
 	 * Get Last Event ID
@@ -53,8 +62,8 @@ struct tcg_swid_attr_tag_id_inv_t {
 	 * @param eid_epoch			Event ID Epoch
 	 * @return					Last Event ID
 	 */
-	u_int32_t (*get_last_eid)(tcg_swid_attr_tag_id_inv_t *this,
-							  u_int32_t *eid_epoch);
+	uint32_t (*get_last_eid)(tcg_swid_attr_tag_id_inv_t *this,
+							 uint32_t *eid_epoch);
 
 	/**
 	 * Get Inventory of SWID tag IDs
@@ -71,12 +80,10 @@ struct tcg_swid_attr_tag_id_inv_t {
  * @param request_id			Copy of the Request ID
  * @param eid_epoch				Event ID Epoch
  * @param eid					Last Event ID
- * @param inventory				SWID Tag Inventory
  */
-pa_tnc_attr_t* tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
-											   u_int32_t eid_epoch,
-											   u_int32_t eid,
-											   swid_inventory_t *inventory);
+pa_tnc_attr_t* tcg_swid_attr_tag_id_inv_create(uint32_t request_id,
+											   uint32_t eid_epoch,
+											   uint32_t eid);
 
 /**
  * Creates an tcg_swid_attr_tag_id_inv_t object from received data
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c
index 82b9ef9..fbb94c6 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@ typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t;
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *  |                           Last EID                            |
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *  |   Unique Sequence ID Length   |Unique Sequence ID (var length)|
+ *  |    Tag File Path Length       |  Tag File Path (var length)   |
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *  |                          Tag Length                           |
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -46,8 +46,7 @@ typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t;
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
 
-#define SWID_TAG_INV_SIZE			16
-#define SWID_TAG_INV_RESERVED		0x00
+#define TCG_SWID_TAG_INV_RESERVED	0x00
 
 /**
  * Private data of an tcg_swid_attr_tag_inv_t object.
@@ -77,17 +76,17 @@ struct private_tcg_swid_attr_tag_inv_t {
 	/**
 	 * Request ID
 	 */
-	u_int32_t request_id;
+	uint32_t request_id;
 
 	/**
 	 * Event ID Epoch
 	 */
-	u_int32_t eid_epoch;
+	uint32_t eid_epoch;
 
 	/**
 	 * Last Event ID
 	 */
-	u_int32_t last_eid;
+	uint32_t last_eid;
 
 	/**
 	 * SWID Tag Inventory
@@ -136,8 +135,8 @@ METHOD(pa_tnc_attr_t, build, void,
 		return;
 	}
 
-	writer = bio_writer_create(SWID_TAG_INV_SIZE);
-	writer->write_uint8 (writer, SWID_TAG_INV_RESERVED);
+	writer = bio_writer_create(TCG_SWID_TAG_INV_MIN_SIZE);
+	writer->write_uint8 (writer, TCG_SWID_TAG_INV_RESERVED);
 	writer->write_uint24(writer, this->inventory->get_count(this->inventory));
 	writer->write_uint32(writer, this->request_id);
 	writer->write_uint32(writer, this->eid_epoch);
@@ -146,7 +145,7 @@ METHOD(pa_tnc_attr_t, build, void,
 	enumerator = this->inventory->create_enumerator(this->inventory);
 	while (enumerator->enumerate(enumerator, &tag))
 	{
-		writer->write_data16(writer, tag->get_unique_seq_id(tag));
+		writer->write_data16(writer, tag->get_tag_file_path(tag));
 		writer->write_data32(writer, tag->get_encoding(tag));
 	}
 	enumerator->destroy(enumerator);
@@ -156,15 +155,15 @@ METHOD(pa_tnc_attr_t, build, void,
 }
 
 METHOD(pa_tnc_attr_t, process, status_t,
-	private_tcg_swid_attr_tag_inv_t *this, u_int32_t *offset)
+	private_tcg_swid_attr_tag_inv_t *this, uint32_t *offset)
 {
 	bio_reader_t *reader;
-	u_int32_t tag_count;
-	u_int8_t reserved;
-	chunk_t tag_encoding, unique_seq_id;
+	uint32_t tag_count;
+	uint8_t reserved;
+	chunk_t tag_encoding, tag_file_path;
 	swid_tag_t *tag;
 
-	if (this->value.len < SWID_TAG_INV_SIZE)
+	if (this->value.len < TCG_SWID_TAG_INV_MIN_SIZE)
 	{
 		DBG1(DBG_TNC, "insufficient data for SWID Tag Inventory");
 		*offset = 0;
@@ -177,16 +176,16 @@ METHOD(pa_tnc_attr_t, process, status_t,
 	reader->read_uint32(reader, &this->request_id);
 	reader->read_uint32(reader, &this->eid_epoch);
 	reader->read_uint32(reader, &this->last_eid);
-	*offset = SWID_TAG_INV_SIZE;
+	*offset = TCG_SWID_TAG_INV_MIN_SIZE;
 
 	while (tag_count--)
 	{
-		if (!reader->read_data16(reader, &unique_seq_id))
+		if (!reader->read_data16(reader, &tag_file_path))
 		{
-			DBG1(DBG_TNC, "insufficient data for Unique Sequence ID");
+			DBG1(DBG_TNC, "insufficient data for Tag File Path");
 			return FAILED;
 		}
-		*offset += 2 + unique_seq_id.len;
+		*offset += 2 + tag_file_path.len;
 
 		if (!reader->read_data32(reader, &tag_encoding))
 		{
@@ -195,7 +194,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
 		}
 		*offset += 4 + tag_encoding.len;
 
-		tag = swid_tag_create(tag_encoding, unique_seq_id);
+		tag = swid_tag_create(tag_encoding, tag_file_path);
 		this->inventory->add(this->inventory, tag);
 	}
 	reader->destroy(reader);
@@ -221,14 +220,20 @@ METHOD(pa_tnc_attr_t, destroy, void,
 	}
 }
 
-METHOD(tcg_swid_attr_tag_inv_t, get_request_id, u_int32_t,
+METHOD(tcg_swid_attr_tag_inv_t, add, void,
+	private_tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag)
+{
+	this->inventory->add(this->inventory, tag);
+}
+
+METHOD(tcg_swid_attr_tag_inv_t, get_request_id, uint32_t,
 	private_tcg_swid_attr_tag_inv_t *this)
 {
 	return this->request_id;
 }
 
-METHOD(tcg_swid_attr_tag_inv_t, get_last_eid, u_int32_t,
-	private_tcg_swid_attr_tag_inv_t *this, u_int32_t *eid_epoch)
+METHOD(tcg_swid_attr_tag_inv_t, get_last_eid, uint32_t,
+	private_tcg_swid_attr_tag_inv_t *this, uint32_t *eid_epoch)
 {
 	if (eid_epoch)
 	{
@@ -246,9 +251,8 @@ METHOD(tcg_swid_attr_tag_inv_t, get_inventory, swid_inventory_t*,
 /**
  * Described in header.
  */
-pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(u_int32_t request_id,
-											u_int32_t eid_epoch, u_int32_t eid,
-											swid_inventory_t *inventory)
+pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(uint32_t request_id,
+											uint32_t eid_epoch, uint32_t eid)
 {
 	private_tcg_swid_attr_tag_inv_t *this;
 
@@ -264,6 +268,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(u_int32_t request_id,
 				.get_ref = _get_ref,
 				.destroy = _destroy,
 			},
+			.add = _add,
 			.get_request_id = _get_request_id,
 			.get_last_eid = _get_last_eid,
 			.get_inventory = _get_inventory,
@@ -272,7 +277,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(u_int32_t request_id,
 		.request_id = request_id,
 		.eid_epoch = eid_epoch,
 		.last_eid = eid,
-		.inventory = inventory,
+		.inventory = swid_inventory_create(TRUE),
 		.ref = 1,
 	);
 
@@ -299,6 +304,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_inv_create_from_data(chunk_t data)
 				.get_ref = _get_ref,
 				.destroy = _destroy,
 			},
+			.add = _add,
 			.get_request_id = _get_request_id,
 			.get_last_eid = _get_last_eid,
 			.get_inventory = _get_inventory,
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h
index 433f55e..69966c7 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@ typedef struct tcg_swid_attr_tag_inv_t tcg_swid_attr_tag_inv_t;
 
 #include <pa_tnc/pa_tnc_attr.h>
 
+#define TCG_SWID_TAG_INV_MIN_SIZE	16
+
 /**
  * Class implementing the TCG SWID Tag Inventory attribute
  *
@@ -41,11 +43,17 @@ struct tcg_swid_attr_tag_inv_t {
 	pa_tnc_attr_t pa_tnc_attribute;
 
 	/**
+	 * Add a Tag ID to the attribute
+	 *
+	 * @param tag				SWID Tag to be added
+	 */
+	void (*add)(tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag);
+	/**
 	 * Get Request ID
 	 *
 	 * @return					Request ID
 	 */
-	u_int32_t (*get_request_id)(tcg_swid_attr_tag_inv_t *this);
+	uint32_t (*get_request_id)(tcg_swid_attr_tag_inv_t *this);
 
 	/**
 	 * Get Last Event ID
@@ -53,8 +61,8 @@ struct tcg_swid_attr_tag_inv_t {
 	 * @param eid_epoch			Event ID Epoch
 	 * @return					Last Event ID
 	 */
-	u_int32_t (*get_last_eid)(tcg_swid_attr_tag_inv_t *this,
-							  u_int32_t *eid_epoch);
+	uint32_t (*get_last_eid)(tcg_swid_attr_tag_inv_t *this,
+							  uint32_t *eid_epoch);
 
 	/**
 	 * Get Inventory of SWID tags
@@ -71,12 +79,10 @@ struct tcg_swid_attr_tag_inv_t {
  * @param request_id			Copy of the Request ID
  * @param eid_epoch				Event ID Epoch
  * @param eid					Last Event ID
- * @param inventory				SWID Tag Inventory
  */
-pa_tnc_attr_t* tcg_swid_attr_tag_inv_create(u_int32_t request_id,
-											u_int32_t eid_epoch,
-											u_int32_t eid,
-											swid_inventory_t *inventory);
+pa_tnc_attr_t* tcg_swid_attr_tag_inv_create(uint32_t request_id,
+											uint32_t eid_epoch,
+											uint32_t eid);
 
 /**
  * Creates an tcg_swid_attr_tag_inv_t object from received data
diff --git a/src/libpttls/Makefile.am b/src/libpttls/Makefile.am
index f2bcf44..7e67600 100644
--- a/src/libpttls/Makefile.am
+++ b/src/libpttls/Makefile.am
@@ -13,6 +13,10 @@ libpttls_la_LIBADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libtls/libtls.la
 
+if USE_WINDOWS
+  libpttls_la_LIBADD += -lws2_32
+endif
+
 libpttls_la_SOURCES = pt_tls.c pt_tls.h \
 	pt_tls_client.c pt_tls_client.h \
 	pt_tls_server.c pt_tls_server.h \
diff --git a/src/libpttls/Makefile.in b/src/libpttls/Makefile.in
index 788c8ca..ff380ce 100644
--- a/src/libpttls/Makefile.in
+++ b/src/libpttls/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -78,6 +78,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
+ at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
 subdir = src/libpttls
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -127,9 +128,10 @@ am__uninstall_files_from_dir = { \
   }
 am__installdirs = "$(DESTDIR)$(ipseclibdir)"
 LTLIBRARIES = $(ipseclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
 libpttls_la_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libtls/libtls.la
+	$(top_builddir)/src/libtls/libtls.la $(am__DEPENDENCIES_1)
 am__dirstamp = $(am__leading_dot)dirstamp
 am_libpttls_la_OBJECTS = pt_tls.lo pt_tls_client.lo pt_tls_server.lo \
 	pt_tls_dispatcher.lo sasl/sasl_plain/sasl_plain.lo \
@@ -262,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -280,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -307,6 +311,7 @@ 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@
@@ -398,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,10 +424,9 @@ AM_LDFLAGS = \
 	-no-undefined
 
 ipseclib_LTLIBRARIES = libpttls.la
-libpttls_la_LIBADD = \
+libpttls_la_LIBADD =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libtls/libtls.la
-
+	$(top_builddir)/src/libtls/libtls.la $(am__append_1)
 libpttls_la_SOURCES = pt_tls.c pt_tls.h \
 	pt_tls_client.c pt_tls_client.h \
 	pt_tls_server.c pt_tls_server.h \
diff --git a/src/libpttls/pt_tls.h b/src/libpttls/pt_tls.h
index 275dc89..b2f3198 100644
--- a/src/libpttls/pt_tls.h
+++ b/src/libpttls/pt_tls.h
@@ -40,7 +40,7 @@
 /**
  * Maximum size of a PT-TLS message
  */
-#define PT_TLS_MAX_MESSAGE_LEN	 8 * TLS_MAX_FRAGMENT_LEN - PT_TLS_HEADER_LEN
+#define PT_TLS_MAX_MESSAGE_LEN	128 * TLS_MAX_FRAGMENT_LEN - PT_TLS_HEADER_LEN
 
 /**
  * Default PT-TLS port
diff --git a/src/libradius/Makefile.in b/src/libradius/Makefile.in
index 6e687a3..76c9f96 100644
--- a/src/libradius/Makefile.in
+++ b/src/libradius/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -259,6 +259,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -277,6 +278,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -304,6 +306,7 @@ 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@
@@ -395,6 +398,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/libsimaka/Makefile.in b/src/libsimaka/Makefile.in
index cb27f05..cbfb8c0 100644
--- a/src/libsimaka/Makefile.in
+++ b/src/libsimaka/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -259,6 +259,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -277,6 +278,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -304,6 +306,7 @@ 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@
@@ -395,6 +398,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/libsimaka/simaka_message.h b/src/libsimaka/simaka_message.h
index 32c39a3..9e2c7de 100644
--- a/src/libsimaka/simaka_message.h
+++ b/src/libsimaka/simaka_message.h
@@ -26,7 +26,7 @@
 #ifndef SIMAKA_MESSAGE_H_
 #define SIMAKA_MESSAGE_H_
 
-#include <utils/enum.h>
+#include <utils/utils.h>
 #include <eap/eap.h>
 
 #include "simaka_crypto.h"
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
index 2b58db5..3ddd42f 100644
--- a/src/libstrongswan/Android.mk
+++ b/src/libstrongswan/Android.mk
@@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 # copy-n-paste from Makefile.am
-LOCAL_SRC_FILES := \
+libstrongswan_la_SOURCES = \
 library.c \
 asn1/asn1.c asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c bio/bio_writer.c \
 collections/blocking_queue.c collections/enumerator.c collections/hashtable.c \
@@ -27,17 +27,31 @@ credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
 database/database_factory.c fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
 ipsec/ipsec_types.c \
 networking/host.c networking/host_resolver.c networking/packet.c \
-networking/tun_device.c networking/streams/stream.c \
-networking/streams/stream_service.c networking/streams/stream_manager.c \
+networking/tun_device.c networking/streams/stream_manager.c \
+networking/streams/stream.c networking/streams/stream_service.c \
+networking/streams/stream_tcp.c networking/streams/stream_service_tcp.c \
 pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
 processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
-selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
-threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+selectors/traffic_selector.c settings/settings.c settings/settings_types.c \
+settings/settings_parser.c settings/settings_lexer.c \
 utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
 utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
-utils/printf_hook/printf_hook_builtin.c utils/settings.c utils/test.c \
-utils/utils/strerror.c
+utils/parser_helper.c utils/test.c utils/utils/strerror.c
+
+libstrongswan_la_SOURCES += \
+    threading/thread.c \
+    threading/thread_value.c \
+    threading/mutex.c \
+    threading/rwlock.c \
+    threading/spinlock.c \
+    threading/semaphore.c \
+    networking/streams/stream_unix.c \
+    networking/streams/stream_service_unix.c
+
+libstrongswan_la_SOURCES += utils/printf_hook/printf_hook_builtin.c
+
+LOCAL_SRC_FILES := $(libstrongswan_la_SOURCES)
 
 # adding the plugin source files
 
@@ -70,7 +84,7 @@ LOCAL_SRC_FILES += $(call add_plugin, nonce)
 LOCAL_SRC_FILES += $(call add_plugin, openssl)
 ifneq ($(call plugin_enabled, openssl),)
 LOCAL_C_INCLUDES += $(openssl_PATH)
-LOCAL_SHARED_LIBRARIES += libcrypto
+LOCAL_STATIC_LIBRARIES += libcrypto_static
 endif
 
 LOCAL_SRC_FILES += $(call add_plugin, pem)
diff --git a/src/libstrongswan/AndroidConfigLocal.h b/src/libstrongswan/AndroidConfigLocal.h
index ee29c16..ae0e606 100644
--- a/src/libstrongswan/AndroidConfigLocal.h
+++ b/src/libstrongswan/AndroidConfigLocal.h
@@ -20,5 +20,3 @@
  * actually defined. */
 
 #undef HAVE_BACKTRACE
-#undef HAVE_DLADDR
-
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 3462d2f..3fb57de 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -25,17 +25,33 @@ credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
 database/database_factory.c fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
 ipsec/ipsec_types.c \
 networking/host.c networking/host_resolver.c networking/packet.c \
-networking/tun_device.c networking/streams/stream.c \
-networking/streams/stream_service.c networking/streams/stream_manager.c \
+networking/tun_device.c networking/streams/stream_manager.c \
+networking/streams/stream.c networking/streams/stream_service.c \
+networking/streams/stream_tcp.c networking/streams/stream_service_tcp.c \
 pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \
 processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
-selectors/traffic_selector.c threading/thread.c threading/thread_value.c \
-threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+selectors/traffic_selector.c settings/settings.c settings/settings_types.c \
+settings/settings_parser.y settings/settings_lexer.l \
 utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
 utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
-utils/settings.c utils/test.c \
-utils/utils/strerror.c
+utils/parser_helper.c utils/test.c utils/utils/strerror.c
+
+if !USE_WINDOWS
+  libstrongswan_la_SOURCES += \
+    threading/thread.c \
+    threading/thread_value.c \
+    threading/mutex.c \
+    threading/rwlock.c \
+    threading/spinlock.c \
+    threading/semaphore.c \
+    networking/streams/stream_unix.c \
+    networking/streams/stream_service_unix.c
+endif
+
+# private header files
+noinst_HEADERS = \
+settings/settings_types.h
 
 if USE_DEV_HEADERS
 strongswan_includedir = ${dev_headers}
@@ -43,7 +59,7 @@ nobase_strongswan_include_HEADERS = \
 library.h \
 asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
 collections/blocking_queue.h collections/enumerator.h collections/hashtable.h \
-collections/linked_list.h collections/array.h \
+collections/linked_list.h collections/array.h collections/dictionary.h \
 crypto/crypters/crypter.h crypto/hashers/hasher.h crypto/mac.h \
 crypto/proposal/proposal_keywords.h crypto/proposal/proposal_keywords_static.h \
 crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
@@ -69,26 +85,29 @@ database/database.h database/database_factory.h fetcher/fetcher.h \
 fetcher/fetcher_manager.h eap/eap.h pen/pen.h ipsec/ipsec_types.h \
 networking/host.h networking/host_resolver.h networking/packet.h \
 networking/tun_device.h networking/streams/stream.h \
+networking/streams/stream_unix.h networking/streams/stream_service_unix.h \
+networking/streams/stream_tcp.h networking/streams/stream_service_tcp.h \
 networking/streams/stream_service.h networking/streams/stream_manager.h \
 resolver/resolver.h resolver/resolver_response.h resolver/rr_set.h \
 resolver/rr.h resolver/resolver_manager.h \
 plugins/plugin_loader.h plugins/plugin.h plugins/plugin_feature.h \
 processing/jobs/job.h processing/jobs/callback_job.h processing/processor.h \
 processing/scheduler.h processing/watcher.h selectors/traffic_selector.h \
-threading/thread.h threading/thread_value.h \
+settings/settings.h threading/thread_value.h \
+threading/thread.h threading/windows/thread.h \
 threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h \
 threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
 utils/utils.h utils/chunk.h utils/debug.h utils/enum.h utils/identification.h \
 utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
 utils/leak_detective.h utils/printf_hook/printf_hook.h \
 utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \
-utils/settings.h utils/test.h utils/integrity_checker.h \
+utils/parser_helper.h utils/test.h utils/integrity_checker.h utils/windows.h \
 utils/utils/strerror.h
 endif
 
 library.lo :	$(top_builddir)/config.status
 
-libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB) $(BFDLIB) $(UNWINDLIB)
+libstrongswan_la_LIBADD = $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB) $(BFDLIB) $(UNWINDLIB)
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan \
@@ -103,6 +122,27 @@ AM_CFLAGS = \
 AM_LDFLAGS = \
 	-no-undefined
 
+AM_YFLAGS = -v -d
+
+if USE_WINDOWS
+  libstrongswan_la_LIBADD += -lws2_32 -lpsapi
+  libstrongswan_la_SOURCES += \
+    threading/windows/thread.c \
+    threading/windows/thread_value.c \
+    threading/windows/mutex.c \
+    threading/windows/rwlock.c \
+    threading/windows/spinlock.c \
+    threading/windows/semaphore.c \
+    utils/windows.c
+else
+  libstrongswan_la_LIBADD += $(PTHREADLIB)
+endif
+
+if USE_DBGHELP
+  libstrongswan_la_LIBADD += -ldbghelp
+  AM_CPPFLAGS += -DHAVE_DBGHELP
+endif
+
 if USE_LEAK_DETECTIVE
   AM_CPPFLAGS += -DLEAK_DETECTIVE
   libstrongswan_la_SOURCES += utils/leak_detective.c
@@ -144,7 +184,8 @@ Android.mk AndroidConfigLocal.h
 
 BUILT_SOURCES = \
 $(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
-$(srcdir)/crypto/proposal/proposal_keywords_static.c
+$(srcdir)/crypto/proposal/proposal_keywords_static.c \
+settings/settings_parser.h
 
 MAINTAINERCLEANFILES = \
 $(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
@@ -384,6 +425,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_WINHTTP
+  SUBDIRS += plugins/winhttp
+if MONOLITHIC
+  libstrongswan_la_LIBADD += plugins/winhttp/libstrongswan-winhttp.la
+endif
+endif
+
 if USE_UNBOUND
   SUBDIRS += plugins/unbound
 if MONOLITHIC
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index af5ea40..9e8cd3e 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -79,115 +79,143 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at USE_LEAK_DETECTIVE_TRUE@am__append_1 = -DLEAK_DETECTIVE
- at USE_LEAK_DETECTIVE_TRUE@am__append_2 = utils/leak_detective.c
- at USE_LOCK_PROFILER_TRUE@am__append_3 = -DLOCK_PROFILER
- at USE_INTEGRITY_TEST_TRUE@am__append_4 = -DINTEGRITY_TEST
- at USE_INTEGRITY_TEST_TRUE@am__append_5 = utils/integrity_checker.c
- at USE_VSTR_TRUE@am__append_6 = utils/printf_hook/printf_hook_vstr.c
- at USE_VSTR_TRUE@am__append_7 = -lvstr
- at USE_BUILTIN_PRINTF_TRUE@am__append_8 = utils/printf_hook/printf_hook_builtin.c
- at USE_BUILTIN_PRINTF_TRUE@am__append_9 = -lm
- at USE_BUILTIN_PRINTF_FALSE@@USE_VSTR_FALSE at am__append_10 = utils/printf_hook/printf_hook_glibc.c
- at USE_LIBCAP_TRUE@am__append_11 = -lcap
- at USE_AF_ALG_TRUE@am__append_12 = plugins/af_alg
- at MONOLITHIC_TRUE@@USE_AF_ALG_TRUE at am__append_13 = plugins/af_alg/libstrongswan-af-alg.la
- at USE_AES_TRUE@am__append_14 = plugins/aes
- at MONOLITHIC_TRUE@@USE_AES_TRUE at am__append_15 = plugins/aes/libstrongswan-aes.la
- at USE_DES_TRUE@am__append_16 = plugins/des
- at MONOLITHIC_TRUE@@USE_DES_TRUE at am__append_17 = plugins/des/libstrongswan-des.la
- at USE_BLOWFISH_TRUE@am__append_18 = plugins/blowfish
- at MONOLITHIC_TRUE@@USE_BLOWFISH_TRUE at am__append_19 = plugins/blowfish/libstrongswan-blowfish.la
- at USE_RC2_TRUE@am__append_20 = plugins/rc2
- at MONOLITHIC_TRUE@@USE_RC2_TRUE at am__append_21 = plugins/rc2/libstrongswan-rc2.la
- at USE_MD4_TRUE@am__append_22 = plugins/md4
- at MONOLITHIC_TRUE@@USE_MD4_TRUE at am__append_23 = plugins/md4/libstrongswan-md4.la
- at USE_MD5_TRUE@am__append_24 = plugins/md5
- at MONOLITHIC_TRUE@@USE_MD5_TRUE at am__append_25 = plugins/md5/libstrongswan-md5.la
- at USE_SHA1_TRUE@am__append_26 = plugins/sha1
- at MONOLITHIC_TRUE@@USE_SHA1_TRUE at am__append_27 = plugins/sha1/libstrongswan-sha1.la
- at USE_SHA2_TRUE@am__append_28 = plugins/sha2
- at MONOLITHIC_TRUE@@USE_SHA2_TRUE at am__append_29 = plugins/sha2/libstrongswan-sha2.la
- at USE_GMP_TRUE@am__append_30 = plugins/gmp
- at MONOLITHIC_TRUE@@USE_GMP_TRUE at am__append_31 = plugins/gmp/libstrongswan-gmp.la
- at USE_RDRAND_TRUE@am__append_32 = plugins/rdrand
- at MONOLITHIC_TRUE@@USE_RDRAND_TRUE at am__append_33 = plugins/rdrand/libstrongswan-rdrand.la
- at USE_RANDOM_TRUE@am__append_34 = plugins/random
- at MONOLITHIC_TRUE@@USE_RANDOM_TRUE at am__append_35 = plugins/random/libstrongswan-random.la
- at USE_NONCE_TRUE@am__append_36 = plugins/nonce
- at MONOLITHIC_TRUE@@USE_NONCE_TRUE at am__append_37 = plugins/nonce/libstrongswan-nonce.la
- at USE_HMAC_TRUE@am__append_38 = plugins/hmac
- at MONOLITHIC_TRUE@@USE_HMAC_TRUE at am__append_39 = plugins/hmac/libstrongswan-hmac.la
- at USE_CMAC_TRUE@am__append_40 = plugins/cmac
- at MONOLITHIC_TRUE@@USE_CMAC_TRUE at am__append_41 = plugins/cmac/libstrongswan-cmac.la
- at USE_XCBC_TRUE@am__append_42 = plugins/xcbc
- at MONOLITHIC_TRUE@@USE_XCBC_TRUE at am__append_43 = plugins/xcbc/libstrongswan-xcbc.la
- at USE_X509_TRUE@am__append_44 = plugins/x509
- at MONOLITHIC_TRUE@@USE_X509_TRUE at am__append_45 = plugins/x509/libstrongswan-x509.la
- at USE_REVOCATION_TRUE@am__append_46 = plugins/revocation
- at MONOLITHIC_TRUE@@USE_REVOCATION_TRUE at am__append_47 = plugins/revocation/libstrongswan-revocation.la
- at USE_CONSTRAINTS_TRUE@am__append_48 = plugins/constraints
- at MONOLITHIC_TRUE@@USE_CONSTRAINTS_TRUE at am__append_49 = plugins/constraints/libstrongswan-constraints.la
- at USE_ACERT_TRUE@am__append_50 = plugins/acert
- at MONOLITHIC_TRUE@@USE_ACERT_TRUE at am__append_51 = plugins/acert/libstrongswan-acert.la
- at USE_PUBKEY_TRUE@am__append_52 = plugins/pubkey
- at MONOLITHIC_TRUE@@USE_PUBKEY_TRUE at am__append_53 = plugins/pubkey/libstrongswan-pubkey.la
- at USE_PKCS1_TRUE@am__append_54 = plugins/pkcs1
- at MONOLITHIC_TRUE@@USE_PKCS1_TRUE at am__append_55 = plugins/pkcs1/libstrongswan-pkcs1.la
- at USE_PKCS7_TRUE@am__append_56 = plugins/pkcs7
- at MONOLITHIC_TRUE@@USE_PKCS7_TRUE at am__append_57 = plugins/pkcs7/libstrongswan-pkcs7.la
- at USE_PKCS8_TRUE@am__append_58 = plugins/pkcs8
- at MONOLITHIC_TRUE@@USE_PKCS8_TRUE at am__append_59 = plugins/pkcs8/libstrongswan-pkcs8.la
- at USE_PKCS12_TRUE@am__append_60 = plugins/pkcs12
- at MONOLITHIC_TRUE@@USE_PKCS12_TRUE at am__append_61 = plugins/pkcs12/libstrongswan-pkcs12.la
- at USE_PGP_TRUE@am__append_62 = plugins/pgp
- at MONOLITHIC_TRUE@@USE_PGP_TRUE at am__append_63 = plugins/pgp/libstrongswan-pgp.la
- at USE_DNSKEY_TRUE@am__append_64 = plugins/dnskey
- at MONOLITHIC_TRUE@@USE_DNSKEY_TRUE at am__append_65 = plugins/dnskey/libstrongswan-dnskey.la
- at USE_SSHKEY_TRUE@am__append_66 = plugins/sshkey
- at MONOLITHIC_TRUE@@USE_SSHKEY_TRUE at am__append_67 = plugins/sshkey/libstrongswan-sshkey.la
- at USE_PEM_TRUE@am__append_68 = plugins/pem
- at MONOLITHIC_TRUE@@USE_PEM_TRUE at am__append_69 = plugins/pem/libstrongswan-pem.la
- at USE_CURL_TRUE@am__append_70 = plugins/curl
- at MONOLITHIC_TRUE@@USE_CURL_TRUE at am__append_71 = plugins/curl/libstrongswan-curl.la
- at USE_UNBOUND_TRUE@am__append_72 = plugins/unbound
- at MONOLITHIC_TRUE@@USE_UNBOUND_TRUE at am__append_73 = plugins/unbound/libstrongswan-unbound.la
- at USE_SOUP_TRUE@am__append_74 = plugins/soup
- at MONOLITHIC_TRUE@@USE_SOUP_TRUE at am__append_75 = plugins/soup/libstrongswan-soup.la
- at USE_LDAP_TRUE@am__append_76 = plugins/ldap
- at MONOLITHIC_TRUE@@USE_LDAP_TRUE at am__append_77 = plugins/ldap/libstrongswan-ldap.la
- at USE_MYSQL_TRUE@am__append_78 = plugins/mysql
- at MONOLITHIC_TRUE@@USE_MYSQL_TRUE at am__append_79 = plugins/mysql/libstrongswan-mysql.la
- at USE_SQLITE_TRUE@am__append_80 = plugins/sqlite
- at MONOLITHIC_TRUE@@USE_SQLITE_TRUE at am__append_81 = plugins/sqlite/libstrongswan-sqlite.la
- at USE_PADLOCK_TRUE@am__append_82 = plugins/padlock
- at MONOLITHIC_TRUE@@USE_PADLOCK_TRUE at am__append_83 = plugins/padlock/libstrongswan-padlock.la
- at USE_OPENSSL_TRUE@am__append_84 = plugins/openssl
- at MONOLITHIC_TRUE@@USE_OPENSSL_TRUE at am__append_85 = plugins/openssl/libstrongswan-openssl.la
- at USE_GCRYPT_TRUE@am__append_86 = plugins/gcrypt
- at MONOLITHIC_TRUE@@USE_GCRYPT_TRUE at am__append_87 = plugins/gcrypt/libstrongswan-gcrypt.la
- at USE_FIPS_PRF_TRUE@am__append_88 = plugins/fips_prf
- at MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE at am__append_89 = plugins/fips_prf/libstrongswan-fips-prf.la
- at USE_AGENT_TRUE@am__append_90 = plugins/agent
- at MONOLITHIC_TRUE@@USE_AGENT_TRUE at am__append_91 = plugins/agent/libstrongswan-agent.la
- at USE_KEYCHAIN_TRUE@am__append_92 = plugins/keychain
- at MONOLITHIC_TRUE@@USE_KEYCHAIN_TRUE at am__append_93 = plugins/keychain/libstrongswan-keychain.la
- at USE_PKCS11_TRUE@am__append_94 = plugins/pkcs11
- at MONOLITHIC_TRUE@@USE_PKCS11_TRUE at am__append_95 = plugins/pkcs11/libstrongswan-pkcs11.la
- at USE_CTR_TRUE@am__append_96 = plugins/ctr
- at MONOLITHIC_TRUE@@USE_CTR_TRUE at am__append_97 = plugins/ctr/libstrongswan-ctr.la
- at USE_CCM_TRUE@am__append_98 = plugins/ccm
- at MONOLITHIC_TRUE@@USE_CCM_TRUE at am__append_99 = plugins/ccm/libstrongswan-ccm.la
- at USE_GCM_TRUE@am__append_100 = plugins/gcm
- at MONOLITHIC_TRUE@@USE_GCM_TRUE at am__append_101 = plugins/gcm/libstrongswan-gcm.la
- at USE_NTRU_TRUE@am__append_102 = plugins/ntru
- at MONOLITHIC_TRUE@@USE_NTRU_TRUE at am__append_103 = plugins/ntru/libstrongswan-ntru.la
- at USE_TEST_VECTORS_TRUE@am__append_104 = plugins/test_vectors
- at MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE at am__append_105 = plugins/test_vectors/libstrongswan-test-vectors.la
+ at USE_WINDOWS_FALSE@am__append_1 = \
+ at USE_WINDOWS_FALSE@    threading/thread.c \
+ at USE_WINDOWS_FALSE@    threading/thread_value.c \
+ at USE_WINDOWS_FALSE@    threading/mutex.c \
+ at USE_WINDOWS_FALSE@    threading/rwlock.c \
+ at USE_WINDOWS_FALSE@    threading/spinlock.c \
+ at USE_WINDOWS_FALSE@    threading/semaphore.c \
+ at USE_WINDOWS_FALSE@    networking/streams/stream_unix.c \
+ at USE_WINDOWS_FALSE@    networking/streams/stream_service_unix.c
+
+ at USE_WINDOWS_TRUE@am__append_2 = -lws2_32 -lpsapi
+ at USE_WINDOWS_TRUE@am__append_3 = \
+ at USE_WINDOWS_TRUE@    threading/windows/thread.c \
+ at USE_WINDOWS_TRUE@    threading/windows/thread_value.c \
+ at USE_WINDOWS_TRUE@    threading/windows/mutex.c \
+ at USE_WINDOWS_TRUE@    threading/windows/rwlock.c \
+ at USE_WINDOWS_TRUE@    threading/windows/spinlock.c \
+ at USE_WINDOWS_TRUE@    threading/windows/semaphore.c \
+ at USE_WINDOWS_TRUE@    utils/windows.c
+
+ at USE_WINDOWS_FALSE@am__append_4 = $(PTHREADLIB)
+ at USE_DBGHELP_TRUE@am__append_5 = -ldbghelp
+ at USE_DBGHELP_TRUE@am__append_6 = -DHAVE_DBGHELP
+ at USE_LEAK_DETECTIVE_TRUE@am__append_7 = -DLEAK_DETECTIVE
+ at USE_LEAK_DETECTIVE_TRUE@am__append_8 = utils/leak_detective.c
+ at USE_LOCK_PROFILER_TRUE@am__append_9 = -DLOCK_PROFILER
+ at USE_INTEGRITY_TEST_TRUE@am__append_10 = -DINTEGRITY_TEST
+ at USE_INTEGRITY_TEST_TRUE@am__append_11 = utils/integrity_checker.c
+ at USE_VSTR_TRUE@am__append_12 = utils/printf_hook/printf_hook_vstr.c
+ at USE_VSTR_TRUE@am__append_13 = -lvstr
+ at USE_BUILTIN_PRINTF_TRUE@am__append_14 = utils/printf_hook/printf_hook_builtin.c
+ at USE_BUILTIN_PRINTF_TRUE@am__append_15 = -lm
+ at USE_BUILTIN_PRINTF_FALSE@@USE_VSTR_FALSE at am__append_16 = utils/printf_hook/printf_hook_glibc.c
+ at USE_LIBCAP_TRUE@am__append_17 = -lcap
+ at USE_AF_ALG_TRUE@am__append_18 = plugins/af_alg
+ at MONOLITHIC_TRUE@@USE_AF_ALG_TRUE at am__append_19 = plugins/af_alg/libstrongswan-af-alg.la
+ at USE_AES_TRUE@am__append_20 = plugins/aes
+ at MONOLITHIC_TRUE@@USE_AES_TRUE at am__append_21 = plugins/aes/libstrongswan-aes.la
+ at USE_DES_TRUE@am__append_22 = plugins/des
+ at MONOLITHIC_TRUE@@USE_DES_TRUE at am__append_23 = plugins/des/libstrongswan-des.la
+ at USE_BLOWFISH_TRUE@am__append_24 = plugins/blowfish
+ at MONOLITHIC_TRUE@@USE_BLOWFISH_TRUE at am__append_25 = plugins/blowfish/libstrongswan-blowfish.la
+ at USE_RC2_TRUE@am__append_26 = plugins/rc2
+ at MONOLITHIC_TRUE@@USE_RC2_TRUE at am__append_27 = plugins/rc2/libstrongswan-rc2.la
+ at USE_MD4_TRUE@am__append_28 = plugins/md4
+ at MONOLITHIC_TRUE@@USE_MD4_TRUE at am__append_29 = plugins/md4/libstrongswan-md4.la
+ at USE_MD5_TRUE@am__append_30 = plugins/md5
+ at MONOLITHIC_TRUE@@USE_MD5_TRUE at am__append_31 = plugins/md5/libstrongswan-md5.la
+ at USE_SHA1_TRUE@am__append_32 = plugins/sha1
+ at MONOLITHIC_TRUE@@USE_SHA1_TRUE at am__append_33 = plugins/sha1/libstrongswan-sha1.la
+ at USE_SHA2_TRUE@am__append_34 = plugins/sha2
+ at MONOLITHIC_TRUE@@USE_SHA2_TRUE at am__append_35 = plugins/sha2/libstrongswan-sha2.la
+ at USE_GMP_TRUE@am__append_36 = plugins/gmp
+ at MONOLITHIC_TRUE@@USE_GMP_TRUE at am__append_37 = plugins/gmp/libstrongswan-gmp.la
+ at USE_RDRAND_TRUE@am__append_38 = plugins/rdrand
+ at MONOLITHIC_TRUE@@USE_RDRAND_TRUE at am__append_39 = plugins/rdrand/libstrongswan-rdrand.la
+ at USE_RANDOM_TRUE@am__append_40 = plugins/random
+ at MONOLITHIC_TRUE@@USE_RANDOM_TRUE at am__append_41 = plugins/random/libstrongswan-random.la
+ at USE_NONCE_TRUE@am__append_42 = plugins/nonce
+ at MONOLITHIC_TRUE@@USE_NONCE_TRUE at am__append_43 = plugins/nonce/libstrongswan-nonce.la
+ at USE_HMAC_TRUE@am__append_44 = plugins/hmac
+ at MONOLITHIC_TRUE@@USE_HMAC_TRUE at am__append_45 = plugins/hmac/libstrongswan-hmac.la
+ at USE_CMAC_TRUE@am__append_46 = plugins/cmac
+ at MONOLITHIC_TRUE@@USE_CMAC_TRUE at am__append_47 = plugins/cmac/libstrongswan-cmac.la
+ at USE_XCBC_TRUE@am__append_48 = plugins/xcbc
+ at MONOLITHIC_TRUE@@USE_XCBC_TRUE at am__append_49 = plugins/xcbc/libstrongswan-xcbc.la
+ at USE_X509_TRUE@am__append_50 = plugins/x509
+ at MONOLITHIC_TRUE@@USE_X509_TRUE at am__append_51 = plugins/x509/libstrongswan-x509.la
+ at USE_REVOCATION_TRUE@am__append_52 = plugins/revocation
+ at MONOLITHIC_TRUE@@USE_REVOCATION_TRUE at am__append_53 = plugins/revocation/libstrongswan-revocation.la
+ at USE_CONSTRAINTS_TRUE@am__append_54 = plugins/constraints
+ at MONOLITHIC_TRUE@@USE_CONSTRAINTS_TRUE at am__append_55 = plugins/constraints/libstrongswan-constraints.la
+ at USE_ACERT_TRUE@am__append_56 = plugins/acert
+ at MONOLITHIC_TRUE@@USE_ACERT_TRUE at am__append_57 = plugins/acert/libstrongswan-acert.la
+ at USE_PUBKEY_TRUE@am__append_58 = plugins/pubkey
+ at MONOLITHIC_TRUE@@USE_PUBKEY_TRUE at am__append_59 = plugins/pubkey/libstrongswan-pubkey.la
+ at USE_PKCS1_TRUE@am__append_60 = plugins/pkcs1
+ at MONOLITHIC_TRUE@@USE_PKCS1_TRUE at am__append_61 = plugins/pkcs1/libstrongswan-pkcs1.la
+ at USE_PKCS7_TRUE@am__append_62 = plugins/pkcs7
+ at MONOLITHIC_TRUE@@USE_PKCS7_TRUE at am__append_63 = plugins/pkcs7/libstrongswan-pkcs7.la
+ at USE_PKCS8_TRUE@am__append_64 = plugins/pkcs8
+ at MONOLITHIC_TRUE@@USE_PKCS8_TRUE at am__append_65 = plugins/pkcs8/libstrongswan-pkcs8.la
+ at USE_PKCS12_TRUE@am__append_66 = plugins/pkcs12
+ at MONOLITHIC_TRUE@@USE_PKCS12_TRUE at am__append_67 = plugins/pkcs12/libstrongswan-pkcs12.la
+ at USE_PGP_TRUE@am__append_68 = plugins/pgp
+ at MONOLITHIC_TRUE@@USE_PGP_TRUE at am__append_69 = plugins/pgp/libstrongswan-pgp.la
+ at USE_DNSKEY_TRUE@am__append_70 = plugins/dnskey
+ at MONOLITHIC_TRUE@@USE_DNSKEY_TRUE at am__append_71 = plugins/dnskey/libstrongswan-dnskey.la
+ at USE_SSHKEY_TRUE@am__append_72 = plugins/sshkey
+ at MONOLITHIC_TRUE@@USE_SSHKEY_TRUE at am__append_73 = plugins/sshkey/libstrongswan-sshkey.la
+ at USE_PEM_TRUE@am__append_74 = plugins/pem
+ at MONOLITHIC_TRUE@@USE_PEM_TRUE at am__append_75 = plugins/pem/libstrongswan-pem.la
+ at USE_CURL_TRUE@am__append_76 = plugins/curl
+ at MONOLITHIC_TRUE@@USE_CURL_TRUE at am__append_77 = plugins/curl/libstrongswan-curl.la
+ at USE_WINHTTP_TRUE@am__append_78 = plugins/winhttp
+ at MONOLITHIC_TRUE@@USE_WINHTTP_TRUE at am__append_79 = plugins/winhttp/libstrongswan-winhttp.la
+ at USE_UNBOUND_TRUE@am__append_80 = plugins/unbound
+ at MONOLITHIC_TRUE@@USE_UNBOUND_TRUE at am__append_81 = plugins/unbound/libstrongswan-unbound.la
+ at USE_SOUP_TRUE@am__append_82 = plugins/soup
+ at MONOLITHIC_TRUE@@USE_SOUP_TRUE at am__append_83 = plugins/soup/libstrongswan-soup.la
+ at USE_LDAP_TRUE@am__append_84 = plugins/ldap
+ at MONOLITHIC_TRUE@@USE_LDAP_TRUE at am__append_85 = plugins/ldap/libstrongswan-ldap.la
+ at USE_MYSQL_TRUE@am__append_86 = plugins/mysql
+ at MONOLITHIC_TRUE@@USE_MYSQL_TRUE at am__append_87 = plugins/mysql/libstrongswan-mysql.la
+ at USE_SQLITE_TRUE@am__append_88 = plugins/sqlite
+ at MONOLITHIC_TRUE@@USE_SQLITE_TRUE at am__append_89 = plugins/sqlite/libstrongswan-sqlite.la
+ at USE_PADLOCK_TRUE@am__append_90 = plugins/padlock
+ at MONOLITHIC_TRUE@@USE_PADLOCK_TRUE at am__append_91 = plugins/padlock/libstrongswan-padlock.la
+ at USE_OPENSSL_TRUE@am__append_92 = plugins/openssl
+ at MONOLITHIC_TRUE@@USE_OPENSSL_TRUE at am__append_93 = plugins/openssl/libstrongswan-openssl.la
+ at USE_GCRYPT_TRUE@am__append_94 = plugins/gcrypt
+ at MONOLITHIC_TRUE@@USE_GCRYPT_TRUE at am__append_95 = plugins/gcrypt/libstrongswan-gcrypt.la
+ at USE_FIPS_PRF_TRUE@am__append_96 = plugins/fips_prf
+ at MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE at am__append_97 = plugins/fips_prf/libstrongswan-fips-prf.la
+ at USE_AGENT_TRUE@am__append_98 = plugins/agent
+ at MONOLITHIC_TRUE@@USE_AGENT_TRUE at am__append_99 = plugins/agent/libstrongswan-agent.la
+ at USE_KEYCHAIN_TRUE@am__append_100 = plugins/keychain
+ at MONOLITHIC_TRUE@@USE_KEYCHAIN_TRUE at am__append_101 = plugins/keychain/libstrongswan-keychain.la
+ at USE_PKCS11_TRUE@am__append_102 = plugins/pkcs11
+ at MONOLITHIC_TRUE@@USE_PKCS11_TRUE at am__append_103 = plugins/pkcs11/libstrongswan-pkcs11.la
+ at USE_CTR_TRUE@am__append_104 = plugins/ctr
+ at MONOLITHIC_TRUE@@USE_CTR_TRUE at am__append_105 = plugins/ctr/libstrongswan-ctr.la
+ at USE_CCM_TRUE@am__append_106 = plugins/ccm
+ at MONOLITHIC_TRUE@@USE_CCM_TRUE at am__append_107 = plugins/ccm/libstrongswan-ccm.la
+ at USE_GCM_TRUE@am__append_108 = plugins/gcm
+ at MONOLITHIC_TRUE@@USE_GCM_TRUE at am__append_109 = plugins/gcm/libstrongswan-gcm.la
+ at USE_NTRU_TRUE@am__append_110 = plugins/ntru
+ at MONOLITHIC_TRUE@@USE_NTRU_TRUE at am__append_111 = plugins/ntru/libstrongswan-ntru.la
+ at USE_TEST_VECTORS_TRUE@am__append_112 = plugins/test_vectors
+ at MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE at am__append_113 = plugins/test_vectors/libstrongswan-test-vectors.la
 subdir = src/libstrongswan
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-	$(top_srcdir)/depcomp \
-	$(am__nobase_strongswan_include_HEADERS_DIST)
+	settings/settings_parser.h settings/settings_parser.c \
+	settings/settings_lexer.c $(top_srcdir)/depcomp \
+	$(top_srcdir)/ylwrap \
+	$(am__nobase_strongswan_include_HEADERS_DIST) \
+	$(noinst_HEADERS)
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
 	$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -236,13 +264,14 @@ am__installdirs = "$(DESTDIR)$(ipseclibdir)" \
 	"$(DESTDIR)$(strongswan_includedir)"
 LTLIBRARIES = $(ipseclib_LTLIBRARIES)
 am__DEPENDENCIES_1 =
+ at USE_WINDOWS_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
 libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(am__append_13) $(am__append_15) \
-	$(am__append_17) $(am__append_19) $(am__append_21) \
+	$(am__DEPENDENCIES_1) $(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) \
@@ -256,7 +285,9 @@ libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 	$(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_101) $(am__append_103) $(am__append_105) \
+	$(am__append_107) $(am__append_109) $(am__append_111) \
+	$(am__append_113)
 am__libstrongswan_la_SOURCES_DIST = library.c asn1/asn1.c \
 	asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c \
 	bio/bio_writer.c collections/blocking_queue.c \
@@ -288,29 +319,53 @@ am__libstrongswan_la_SOURCES_DIST = library.c asn1/asn1.c \
 	fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
 	ipsec/ipsec_types.c networking/host.c \
 	networking/host_resolver.c networking/packet.c \
-	networking/tun_device.c networking/streams/stream.c \
+	networking/tun_device.c networking/streams/stream_manager.c \
+	networking/streams/stream.c \
 	networking/streams/stream_service.c \
-	networking/streams/stream_manager.c pen/pen.c \
+	networking/streams/stream_tcp.c \
+	networking/streams/stream_service_tcp.c pen/pen.c \
 	plugins/plugin_loader.c plugins/plugin_feature.c \
 	processing/jobs/job.c processing/jobs/callback_job.c \
 	processing/processor.c processing/scheduler.c \
 	processing/watcher.c resolver/resolver_manager.c \
 	resolver/rr_set.c selectors/traffic_selector.c \
-	threading/thread.c threading/thread_value.c threading/mutex.c \
-	threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+	settings/settings.c settings/settings_types.c \
+	settings/settings_parser.y settings/settings_lexer.l \
 	utils/utils.c utils/chunk.c utils/debug.c utils/enum.c \
 	utils/identification.c utils/lexparser.c utils/optionsfrom.c \
-	utils/capabilities.c utils/backtrace.c utils/settings.c \
-	utils/test.c utils/utils/strerror.c utils/leak_detective.c \
+	utils/capabilities.c utils/backtrace.c utils/parser_helper.c \
+	utils/test.c utils/utils/strerror.c threading/thread.c \
+	threading/thread_value.c threading/mutex.c threading/rwlock.c \
+	threading/spinlock.c threading/semaphore.c \
+	networking/streams/stream_unix.c \
+	networking/streams/stream_service_unix.c \
+	threading/windows/thread.c threading/windows/thread_value.c \
+	threading/windows/mutex.c threading/windows/rwlock.c \
+	threading/windows/spinlock.c threading/windows/semaphore.c \
+	utils/windows.c utils/leak_detective.c \
 	utils/integrity_checker.c utils/printf_hook/printf_hook_vstr.c \
 	utils/printf_hook/printf_hook_builtin.c \
 	utils/printf_hook/printf_hook_glibc.c
 am__dirstamp = $(am__leading_dot)dirstamp
- at USE_LEAK_DETECTIVE_TRUE@am__objects_1 = utils/leak_detective.lo
- at USE_INTEGRITY_TEST_TRUE@am__objects_2 = utils/integrity_checker.lo
- at USE_VSTR_TRUE@am__objects_3 = utils/printf_hook/printf_hook_vstr.lo
- at USE_BUILTIN_PRINTF_TRUE@am__objects_4 = utils/printf_hook/printf_hook_builtin.lo
- at USE_BUILTIN_PRINTF_FALSE@@USE_VSTR_FALSE at am__objects_5 = utils/printf_hook/printf_hook_glibc.lo
+ at USE_WINDOWS_FALSE@am__objects_1 = threading/thread.lo \
+ at USE_WINDOWS_FALSE@	threading/thread_value.lo \
+ at USE_WINDOWS_FALSE@	threading/mutex.lo threading/rwlock.lo \
+ at USE_WINDOWS_FALSE@	threading/spinlock.lo \
+ at USE_WINDOWS_FALSE@	threading/semaphore.lo \
+ at USE_WINDOWS_FALSE@	networking/streams/stream_unix.lo \
+ at USE_WINDOWS_FALSE@	networking/streams/stream_service_unix.lo
+ at USE_WINDOWS_TRUE@am__objects_2 = threading/windows/thread.lo \
+ at USE_WINDOWS_TRUE@	threading/windows/thread_value.lo \
+ at USE_WINDOWS_TRUE@	threading/windows/mutex.lo \
+ at USE_WINDOWS_TRUE@	threading/windows/rwlock.lo \
+ at USE_WINDOWS_TRUE@	threading/windows/spinlock.lo \
+ at USE_WINDOWS_TRUE@	threading/windows/semaphore.lo \
+ at USE_WINDOWS_TRUE@	utils/windows.lo
+ at USE_LEAK_DETECTIVE_TRUE@am__objects_3 = utils/leak_detective.lo
+ at USE_INTEGRITY_TEST_TRUE@am__objects_4 = utils/integrity_checker.lo
+ at USE_VSTR_TRUE@am__objects_5 = utils/printf_hook/printf_hook_vstr.lo
+ at USE_BUILTIN_PRINTF_TRUE@am__objects_6 = utils/printf_hook/printf_hook_builtin.lo
+ at USE_BUILTIN_PRINTF_FALSE@@USE_VSTR_FALSE at am__objects_7 = utils/printf_hook/printf_hook_glibc.lo
 am_libstrongswan_la_OBJECTS = library.lo asn1/asn1.lo \
 	asn1/asn1_parser.lo asn1/oid.lo bio/bio_reader.lo \
 	bio/bio_writer.lo collections/blocking_queue.lo \
@@ -342,22 +397,25 @@ am_libstrongswan_la_OBJECTS = library.lo asn1/asn1.lo \
 	fetcher/fetcher.lo fetcher/fetcher_manager.lo eap/eap.lo \
 	ipsec/ipsec_types.lo networking/host.lo \
 	networking/host_resolver.lo networking/packet.lo \
-	networking/tun_device.lo networking/streams/stream.lo \
+	networking/tun_device.lo networking/streams/stream_manager.lo \
+	networking/streams/stream.lo \
 	networking/streams/stream_service.lo \
-	networking/streams/stream_manager.lo pen/pen.lo \
+	networking/streams/stream_tcp.lo \
+	networking/streams/stream_service_tcp.lo pen/pen.lo \
 	plugins/plugin_loader.lo plugins/plugin_feature.lo \
 	processing/jobs/job.lo processing/jobs/callback_job.lo \
 	processing/processor.lo processing/scheduler.lo \
 	processing/watcher.lo resolver/resolver_manager.lo \
 	resolver/rr_set.lo selectors/traffic_selector.lo \
-	threading/thread.lo threading/thread_value.lo \
-	threading/mutex.lo threading/semaphore.lo threading/rwlock.lo \
-	threading/spinlock.lo utils/utils.lo utils/chunk.lo \
-	utils/debug.lo utils/enum.lo utils/identification.lo \
-	utils/lexparser.lo utils/optionsfrom.lo utils/capabilities.lo \
-	utils/backtrace.lo utils/settings.lo utils/test.lo \
-	utils/utils/strerror.lo $(am__objects_1) $(am__objects_2) \
-	$(am__objects_3) $(am__objects_4) $(am__objects_5)
+	settings/settings.lo settings/settings_types.lo \
+	settings/settings_parser.lo settings/settings_lexer.lo \
+	utils/utils.lo utils/chunk.lo utils/debug.lo utils/enum.lo \
+	utils/identification.lo utils/lexparser.lo \
+	utils/optionsfrom.lo utils/capabilities.lo utils/backtrace.lo \
+	utils/parser_helper.lo utils/test.lo utils/utils/strerror.lo \
+	$(am__objects_1) $(am__objects_2) $(am__objects_3) \
+	$(am__objects_4) $(am__objects_5) $(am__objects_6) \
+	$(am__objects_7)
 libstrongswan_la_OBJECTS = $(am_libstrongswan_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -397,6 +455,23 @@ 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 = 
+LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
+AM_V_LEX = $(am__v_LEX_ at AM_V@)
+am__v_LEX_ = $(am__v_LEX_ at AM_DEFAULT_V@)
+am__v_LEX_0 = @echo "  LEX     " $@;
+am__v_LEX_1 = 
+YLWRAP = $(top_srcdir)/ylwrap
+am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
+		   -e s/c++$$/h++/ -e s/c$$/h/
+YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
+AM_V_YACC = $(am__v_YACC_ at AM_V@)
+am__v_YACC_ = $(am__v_YACC_ at AM_DEFAULT_V@)
+am__v_YACC_0 = @echo "  YACC    " $@;
+am__v_YACC_1 = 
 SOURCES = $(libstrongswan_la_SOURCES)
 DIST_SOURCES = $(am__libstrongswan_la_SOURCES_DIST)
 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
@@ -417,7 +492,8 @@ am__nobase_strongswan_include_HEADERS_DIST = library.h asn1/asn1.h \
 	bio/bio_writer.h collections/blocking_queue.h \
 	collections/enumerator.h collections/hashtable.h \
 	collections/linked_list.h collections/array.h \
-	crypto/crypters/crypter.h crypto/hashers/hasher.h crypto/mac.h \
+	collections/dictionary.h crypto/crypters/crypter.h \
+	crypto/hashers/hasher.h crypto/mac.h \
 	crypto/proposal/proposal_keywords.h \
 	crypto/proposal/proposal_keywords_static.h crypto/prfs/prf.h \
 	crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
@@ -449,6 +525,10 @@ am__nobase_strongswan_include_HEADERS_DIST = library.h asn1/asn1.h \
 	pen/pen.h ipsec/ipsec_types.h networking/host.h \
 	networking/host_resolver.h networking/packet.h \
 	networking/tun_device.h networking/streams/stream.h \
+	networking/streams/stream_unix.h \
+	networking/streams/stream_service_unix.h \
+	networking/streams/stream_tcp.h \
+	networking/streams/stream_service_tcp.h \
 	networking/streams/stream_service.h \
 	networking/streams/stream_manager.h resolver/resolver.h \
 	resolver/resolver_response.h resolver/rr_set.h resolver/rr.h \
@@ -457,18 +537,20 @@ am__nobase_strongswan_include_HEADERS_DIST = library.h asn1/asn1.h \
 	processing/jobs/job.h processing/jobs/callback_job.h \
 	processing/processor.h processing/scheduler.h \
 	processing/watcher.h selectors/traffic_selector.h \
-	threading/thread.h threading/thread_value.h threading/mutex.h \
-	threading/condvar.h threading/spinlock.h threading/semaphore.h \
-	threading/rwlock.h threading/rwlock_condvar.h \
-	threading/lock_profiler.h utils/utils.h utils/chunk.h \
-	utils/debug.h utils/enum.h utils/identification.h \
-	utils/lexparser.h utils/optionsfrom.h utils/capabilities.h \
-	utils/backtrace.h utils/leak_detective.h \
+	settings/settings.h threading/thread_value.h \
+	threading/thread.h threading/windows/thread.h \
+	threading/mutex.h threading/condvar.h threading/spinlock.h \
+	threading/semaphore.h threading/rwlock.h \
+	threading/rwlock_condvar.h threading/lock_profiler.h \
+	utils/utils.h utils/chunk.h utils/debug.h utils/enum.h \
+	utils/identification.h utils/lexparser.h utils/optionsfrom.h \
+	utils/capabilities.h utils/backtrace.h utils/leak_detective.h \
 	utils/printf_hook/printf_hook.h \
 	utils/printf_hook/printf_hook_vstr.h \
-	utils/printf_hook/printf_hook_builtin.h utils/settings.h \
-	utils/test.h utils/integrity_checker.h utils/utils/strerror.h
-HEADERS = $(nobase_strongswan_include_HEADERS)
+	utils/printf_hook/printf_hook_builtin.h utils/parser_helper.h \
+	utils/test.h utils/integrity_checker.h utils/windows.h \
+	utils/utils/strerror.h
+HEADERS = $(nobase_strongswan_include_HEADERS) $(noinst_HEADERS)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
   distclean-recursive maintainer-clean-recursive
 am__recursive_targets = \
@@ -504,11 +586,11 @@ DIST_SUBDIRS = . plugins/af_alg plugins/aes plugins/des \
 	plugins/constraints plugins/acert plugins/pubkey plugins/pkcs1 \
 	plugins/pkcs7 plugins/pkcs8 plugins/pkcs12 plugins/pgp \
 	plugins/dnskey plugins/sshkey plugins/pem plugins/curl \
-	plugins/unbound plugins/soup plugins/ldap plugins/mysql \
-	plugins/sqlite plugins/padlock plugins/openssl plugins/gcrypt \
-	plugins/fips_prf plugins/agent plugins/keychain plugins/pkcs11 \
-	plugins/ctr plugins/ccm plugins/gcm plugins/ntru \
-	plugins/test_vectors tests
+	plugins/winhttp plugins/unbound plugins/soup plugins/ldap \
+	plugins/mysql plugins/sqlite plugins/padlock plugins/openssl \
+	plugins/gcrypt plugins/fips_prf plugins/agent plugins/keychain \
+	plugins/pkcs11 plugins/ctr plugins/ccm plugins/gcm \
+	plugins/ntru plugins/test_vectors tests
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 am__relativize = \
   dir0=`pwd`; \
@@ -597,6 +679,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -615,6 +698,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -642,6 +726,7 @@ 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@
@@ -733,6 +818,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -774,28 +860,35 @@ libstrongswan_la_SOURCES = library.c asn1/asn1.c asn1/asn1_parser.c \
 	fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
 	ipsec/ipsec_types.c networking/host.c \
 	networking/host_resolver.c networking/packet.c \
-	networking/tun_device.c networking/streams/stream.c \
+	networking/tun_device.c networking/streams/stream_manager.c \
+	networking/streams/stream.c \
 	networking/streams/stream_service.c \
-	networking/streams/stream_manager.c pen/pen.c \
+	networking/streams/stream_tcp.c \
+	networking/streams/stream_service_tcp.c pen/pen.c \
 	plugins/plugin_loader.c plugins/plugin_feature.c \
 	processing/jobs/job.c processing/jobs/callback_job.c \
 	processing/processor.c processing/scheduler.c \
 	processing/watcher.c resolver/resolver_manager.c \
 	resolver/rr_set.c selectors/traffic_selector.c \
-	threading/thread.c threading/thread_value.c threading/mutex.c \
-	threading/semaphore.c threading/rwlock.c threading/spinlock.c \
+	settings/settings.c settings/settings_types.c \
+	settings/settings_parser.y settings/settings_lexer.l \
 	utils/utils.c utils/chunk.c utils/debug.c utils/enum.c \
 	utils/identification.c utils/lexparser.c utils/optionsfrom.c \
-	utils/capabilities.c utils/backtrace.c utils/settings.c \
-	utils/test.c utils/utils/strerror.c $(am__append_2) \
-	$(am__append_5) $(am__append_6) $(am__append_8) \
-	$(am__append_10)
+	utils/capabilities.c utils/backtrace.c utils/parser_helper.c \
+	utils/test.c utils/utils/strerror.c $(am__append_1) \
+	$(am__append_3) $(am__append_8) $(am__append_11) \
+	$(am__append_12) $(am__append_14) $(am__append_16)
+
+# private header files
+noinst_HEADERS = \
+settings/settings_types.h
+
 @USE_DEV_HEADERS_TRUE at strongswan_includedir = ${dev_headers}
 @USE_DEV_HEADERS_TRUE at nobase_strongswan_include_HEADERS = \
 @USE_DEV_HEADERS_TRUE at library.h \
 @USE_DEV_HEADERS_TRUE at asn1/asn1.h asn1/asn1_parser.h asn1/oid.h bio/bio_reader.h bio/bio_writer.h \
 @USE_DEV_HEADERS_TRUE at collections/blocking_queue.h collections/enumerator.h collections/hashtable.h \
- at USE_DEV_HEADERS_TRUE@collections/linked_list.h collections/array.h \
+ at USE_DEV_HEADERS_TRUE@collections/linked_list.h collections/array.h collections/dictionary.h \
 @USE_DEV_HEADERS_TRUE at crypto/crypters/crypter.h crypto/hashers/hasher.h crypto/mac.h \
 @USE_DEV_HEADERS_TRUE at crypto/proposal/proposal_keywords.h crypto/proposal/proposal_keywords_static.h \
 @USE_DEV_HEADERS_TRUE at crypto/prfs/prf.h crypto/prfs/mac_prf.h crypto/rngs/rng.h crypto/nonce_gen.h \
@@ -821,52 +914,57 @@ libstrongswan_la_SOURCES = library.c asn1/asn1.c asn1/asn1_parser.c \
 @USE_DEV_HEADERS_TRUE at fetcher/fetcher_manager.h eap/eap.h pen/pen.h ipsec/ipsec_types.h \
 @USE_DEV_HEADERS_TRUE at networking/host.h networking/host_resolver.h networking/packet.h \
 @USE_DEV_HEADERS_TRUE at networking/tun_device.h networking/streams/stream.h \
+ at USE_DEV_HEADERS_TRUE@networking/streams/stream_unix.h networking/streams/stream_service_unix.h \
+ at USE_DEV_HEADERS_TRUE@networking/streams/stream_tcp.h networking/streams/stream_service_tcp.h \
 @USE_DEV_HEADERS_TRUE at networking/streams/stream_service.h networking/streams/stream_manager.h \
 @USE_DEV_HEADERS_TRUE at resolver/resolver.h resolver/resolver_response.h resolver/rr_set.h \
 @USE_DEV_HEADERS_TRUE at resolver/rr.h resolver/resolver_manager.h \
 @USE_DEV_HEADERS_TRUE at plugins/plugin_loader.h plugins/plugin.h plugins/plugin_feature.h \
 @USE_DEV_HEADERS_TRUE at processing/jobs/job.h processing/jobs/callback_job.h processing/processor.h \
 @USE_DEV_HEADERS_TRUE at processing/scheduler.h processing/watcher.h selectors/traffic_selector.h \
- at USE_DEV_HEADERS_TRUE@threading/thread.h threading/thread_value.h \
+ at USE_DEV_HEADERS_TRUE@settings/settings.h threading/thread_value.h \
+ at USE_DEV_HEADERS_TRUE@threading/thread.h threading/windows/thread.h \
 @USE_DEV_HEADERS_TRUE at threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h \
 @USE_DEV_HEADERS_TRUE at threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
 @USE_DEV_HEADERS_TRUE at utils/utils.h utils/chunk.h utils/debug.h utils/enum.h utils/identification.h \
 @USE_DEV_HEADERS_TRUE at utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
 @USE_DEV_HEADERS_TRUE at utils/leak_detective.h utils/printf_hook/printf_hook.h \
 @USE_DEV_HEADERS_TRUE at utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \
- at USE_DEV_HEADERS_TRUE@utils/settings.h utils/test.h utils/integrity_checker.h \
+ at USE_DEV_HEADERS_TRUE@utils/parser_helper.h utils/test.h utils/integrity_checker.h utils/windows.h \
 @USE_DEV_HEADERS_TRUE at utils/utils/strerror.h
 
-libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) \
-	$(RTLIB) $(BFDLIB) $(UNWINDLIB) $(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_55) \
-	$(am__append_57) $(am__append_59) $(am__append_61) \
-	$(am__append_63) $(am__append_65) $(am__append_67) \
-	$(am__append_69) $(am__append_71) $(am__append_73) \
-	$(am__append_75) $(am__append_77) $(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)
+libstrongswan_la_LIBADD = $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB) \
+	$(BFDLIB) $(UNWINDLIB) $(am__append_2) $(am__append_4) \
+	$(am__append_5) $(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_55) $(am__append_57) \
+	$(am__append_59) $(am__append_61) $(am__append_63) \
+	$(am__append_65) $(am__append_67) $(am__append_69) \
+	$(am__append_71) $(am__append_73) $(am__append_75) \
+	$(am__append_77) $(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_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan \
 	-DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_LIB_DIR=\"${ipseclibdir}\" \
 	-DPLUGINDIR=\"${plugindir}\" \
-	-DSTRONGSWAN_CONF=\"${strongswan_conf}\" $(am__append_1) \
-	$(am__append_3) $(am__append_4)
+	-DSTRONGSWAN_CONF=\"${strongswan_conf}\" $(am__append_6) \
+	$(am__append_7) $(am__append_9) $(am__append_10)
 AM_CFLAGS = \
 	@COVERAGE_CFLAGS@
 
 AM_LDFLAGS = \
 	-no-undefined
 
+AM_YFLAGS = -v -d
 EXTRA_DIST = \
 asn1/oid.txt asn1/oid.pl \
 crypto/proposal/proposal_keywords_static.txt \
@@ -874,68 +972,69 @@ Android.mk AndroidConfigLocal.h
 
 BUILT_SOURCES = \
 $(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
-$(srcdir)/crypto/proposal/proposal_keywords_static.c
+$(srcdir)/crypto/proposal/proposal_keywords_static.c \
+settings/settings_parser.h
 
 MAINTAINERCLEANFILES = \
 $(srcdir)/asn1/oid.c $(srcdir)/asn1/oid.h \
 $(srcdir)/crypto/proposal/proposal_keywords_static.c
 
- at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_12) $(am__append_14) \
- at MONOLITHIC_FALSE@	$(am__append_16) $(am__append_18) \
- at MONOLITHIC_FALSE@	$(am__append_20) $(am__append_22) \
- at MONOLITHIC_FALSE@	$(am__append_24) $(am__append_26) \
- at MONOLITHIC_FALSE@	$(am__append_28) $(am__append_30) \
- at MONOLITHIC_FALSE@	$(am__append_32) $(am__append_34) \
- at MONOLITHIC_FALSE@	$(am__append_36) $(am__append_38) \
- at MONOLITHIC_FALSE@	$(am__append_40) $(am__append_42) \
- at MONOLITHIC_FALSE@	$(am__append_44) $(am__append_46) \
- at MONOLITHIC_FALSE@	$(am__append_48) $(am__append_50) \
- at MONOLITHIC_FALSE@	$(am__append_52) $(am__append_54) \
- at MONOLITHIC_FALSE@	$(am__append_56) $(am__append_58) \
- at MONOLITHIC_FALSE@	$(am__append_60) $(am__append_62) \
- at MONOLITHIC_FALSE@	$(am__append_64) $(am__append_66) \
- at MONOLITHIC_FALSE@	$(am__append_68) $(am__append_70) \
- at MONOLITHIC_FALSE@	$(am__append_72) $(am__append_74) \
- at MONOLITHIC_FALSE@	$(am__append_76) $(am__append_78) \
- at MONOLITHIC_FALSE@	$(am__append_80) $(am__append_82) \
- at MONOLITHIC_FALSE@	$(am__append_84) $(am__append_86) \
- at MONOLITHIC_FALSE@	$(am__append_88) $(am__append_90) \
- at MONOLITHIC_FALSE@	$(am__append_92) $(am__append_94) \
- at MONOLITHIC_FALSE@	$(am__append_96) $(am__append_98) \
- at MONOLITHIC_FALSE@	$(am__append_100) $(am__append_102) \
- at MONOLITHIC_FALSE@	$(am__append_104) tests
+ at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_18) $(am__append_20) \
+ at MONOLITHIC_FALSE@	$(am__append_22) $(am__append_24) \
+ at MONOLITHIC_FALSE@	$(am__append_26) $(am__append_28) \
+ at MONOLITHIC_FALSE@	$(am__append_30) $(am__append_32) \
+ at MONOLITHIC_FALSE@	$(am__append_34) $(am__append_36) \
+ at MONOLITHIC_FALSE@	$(am__append_38) $(am__append_40) \
+ at MONOLITHIC_FALSE@	$(am__append_42) $(am__append_44) \
+ at MONOLITHIC_FALSE@	$(am__append_46) $(am__append_48) \
+ at MONOLITHIC_FALSE@	$(am__append_50) $(am__append_52) \
+ at MONOLITHIC_FALSE@	$(am__append_54) $(am__append_56) \
+ at MONOLITHIC_FALSE@	$(am__append_58) $(am__append_60) \
+ at MONOLITHIC_FALSE@	$(am__append_62) $(am__append_64) \
+ at MONOLITHIC_FALSE@	$(am__append_66) $(am__append_68) \
+ at MONOLITHIC_FALSE@	$(am__append_70) $(am__append_72) \
+ at MONOLITHIC_FALSE@	$(am__append_74) $(am__append_76) \
+ at MONOLITHIC_FALSE@	$(am__append_78) $(am__append_80) \
+ at MONOLITHIC_FALSE@	$(am__append_82) $(am__append_84) \
+ at MONOLITHIC_FALSE@	$(am__append_86) $(am__append_88) \
+ at MONOLITHIC_FALSE@	$(am__append_90) $(am__append_92) \
+ at MONOLITHIC_FALSE@	$(am__append_94) $(am__append_96) \
+ at MONOLITHIC_FALSE@	$(am__append_98) $(am__append_100) \
+ at MONOLITHIC_FALSE@	$(am__append_102) $(am__append_104) \
+ at MONOLITHIC_FALSE@	$(am__append_106) $(am__append_108) \
+ at MONOLITHIC_FALSE@	$(am__append_110) $(am__append_112) tests
 
 # build plugins with their own Makefile
 #######################################
- at MONOLITHIC_TRUE@SUBDIRS = $(am__append_12) $(am__append_14) \
- at MONOLITHIC_TRUE@	$(am__append_16) $(am__append_18) \
- at MONOLITHIC_TRUE@	$(am__append_20) $(am__append_22) \
- at MONOLITHIC_TRUE@	$(am__append_24) $(am__append_26) \
- at MONOLITHIC_TRUE@	$(am__append_28) $(am__append_30) \
- at MONOLITHIC_TRUE@	$(am__append_32) $(am__append_34) \
- at MONOLITHIC_TRUE@	$(am__append_36) $(am__append_38) \
- at MONOLITHIC_TRUE@	$(am__append_40) $(am__append_42) \
- at MONOLITHIC_TRUE@	$(am__append_44) $(am__append_46) \
- at MONOLITHIC_TRUE@	$(am__append_48) $(am__append_50) \
- at MONOLITHIC_TRUE@	$(am__append_52) $(am__append_54) \
- at MONOLITHIC_TRUE@	$(am__append_56) $(am__append_58) \
- at MONOLITHIC_TRUE@	$(am__append_60) $(am__append_62) \
- at MONOLITHIC_TRUE@	$(am__append_64) $(am__append_66) \
- at MONOLITHIC_TRUE@	$(am__append_68) $(am__append_70) \
- at MONOLITHIC_TRUE@	$(am__append_72) $(am__append_74) \
- at MONOLITHIC_TRUE@	$(am__append_76) $(am__append_78) \
- at MONOLITHIC_TRUE@	$(am__append_80) $(am__append_82) \
- at MONOLITHIC_TRUE@	$(am__append_84) $(am__append_86) \
- at MONOLITHIC_TRUE@	$(am__append_88) $(am__append_90) \
- at MONOLITHIC_TRUE@	$(am__append_92) $(am__append_94) \
- at MONOLITHIC_TRUE@	$(am__append_96) $(am__append_98) \
- at MONOLITHIC_TRUE@	$(am__append_100) $(am__append_102) \
- at MONOLITHIC_TRUE@	$(am__append_104) . tests
+ at MONOLITHIC_TRUE@SUBDIRS = $(am__append_18) $(am__append_20) \
+ at MONOLITHIC_TRUE@	$(am__append_22) $(am__append_24) \
+ at MONOLITHIC_TRUE@	$(am__append_26) $(am__append_28) \
+ at MONOLITHIC_TRUE@	$(am__append_30) $(am__append_32) \
+ at MONOLITHIC_TRUE@	$(am__append_34) $(am__append_36) \
+ at MONOLITHIC_TRUE@	$(am__append_38) $(am__append_40) \
+ at MONOLITHIC_TRUE@	$(am__append_42) $(am__append_44) \
+ at MONOLITHIC_TRUE@	$(am__append_46) $(am__append_48) \
+ at MONOLITHIC_TRUE@	$(am__append_50) $(am__append_52) \
+ at MONOLITHIC_TRUE@	$(am__append_54) $(am__append_56) \
+ at MONOLITHIC_TRUE@	$(am__append_58) $(am__append_60) \
+ at MONOLITHIC_TRUE@	$(am__append_62) $(am__append_64) \
+ at MONOLITHIC_TRUE@	$(am__append_66) $(am__append_68) \
+ at MONOLITHIC_TRUE@	$(am__append_70) $(am__append_72) \
+ at MONOLITHIC_TRUE@	$(am__append_74) $(am__append_76) \
+ at MONOLITHIC_TRUE@	$(am__append_78) $(am__append_80) \
+ at MONOLITHIC_TRUE@	$(am__append_82) $(am__append_84) \
+ at MONOLITHIC_TRUE@	$(am__append_86) $(am__append_88) \
+ at MONOLITHIC_TRUE@	$(am__append_90) $(am__append_92) \
+ at MONOLITHIC_TRUE@	$(am__append_94) $(am__append_96) \
+ at MONOLITHIC_TRUE@	$(am__append_98) $(am__append_100) \
+ at MONOLITHIC_TRUE@	$(am__append_102) $(am__append_104) \
+ at MONOLITHIC_TRUE@	$(am__append_106) $(am__append_108) \
+ at MONOLITHIC_TRUE@	$(am__append_110) $(am__append_112) . tests
 all: $(BUILT_SOURCES)
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
 
 .SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
+.SUFFIXES: .c .l .lo .o .obj .y
 $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
 	@for dep in $?; do \
 	  case '$(am__configure_deps)' in \
@@ -1248,12 +1347,17 @@ networking/streams/$(am__dirstamp):
 networking/streams/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) networking/streams/$(DEPDIR)
 	@: > networking/streams/$(DEPDIR)/$(am__dirstamp)
+networking/streams/stream_manager.lo:  \
+	networking/streams/$(am__dirstamp) \
+	networking/streams/$(DEPDIR)/$(am__dirstamp)
 networking/streams/stream.lo: networking/streams/$(am__dirstamp) \
 	networking/streams/$(DEPDIR)/$(am__dirstamp)
 networking/streams/stream_service.lo:  \
 	networking/streams/$(am__dirstamp) \
 	networking/streams/$(DEPDIR)/$(am__dirstamp)
-networking/streams/stream_manager.lo:  \
+networking/streams/stream_tcp.lo: networking/streams/$(am__dirstamp) \
+	networking/streams/$(DEPDIR)/$(am__dirstamp)
+networking/streams/stream_service_tcp.lo:  \
 	networking/streams/$(am__dirstamp) \
 	networking/streams/$(DEPDIR)/$(am__dirstamp)
 pen/$(am__dirstamp):
@@ -1313,24 +1417,23 @@ selectors/$(DEPDIR)/$(am__dirstamp):
 	@: > selectors/$(DEPDIR)/$(am__dirstamp)
 selectors/traffic_selector.lo: selectors/$(am__dirstamp) \
 	selectors/$(DEPDIR)/$(am__dirstamp)
-threading/$(am__dirstamp):
-	@$(MKDIR_P) threading
-	@: > threading/$(am__dirstamp)
-threading/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) threading/$(DEPDIR)
-	@: > threading/$(DEPDIR)/$(am__dirstamp)
-threading/thread.lo: threading/$(am__dirstamp) \
-	threading/$(DEPDIR)/$(am__dirstamp)
-threading/thread_value.lo: threading/$(am__dirstamp) \
-	threading/$(DEPDIR)/$(am__dirstamp)
-threading/mutex.lo: threading/$(am__dirstamp) \
-	threading/$(DEPDIR)/$(am__dirstamp)
-threading/semaphore.lo: threading/$(am__dirstamp) \
-	threading/$(DEPDIR)/$(am__dirstamp)
-threading/rwlock.lo: threading/$(am__dirstamp) \
-	threading/$(DEPDIR)/$(am__dirstamp)
-threading/spinlock.lo: threading/$(am__dirstamp) \
-	threading/$(DEPDIR)/$(am__dirstamp)
+settings/$(am__dirstamp):
+	@$(MKDIR_P) settings
+	@: > settings/$(am__dirstamp)
+settings/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) settings/$(DEPDIR)
+	@: > settings/$(DEPDIR)/$(am__dirstamp)
+settings/settings.lo: settings/$(am__dirstamp) \
+	settings/$(DEPDIR)/$(am__dirstamp)
+settings/settings_types.lo: settings/$(am__dirstamp) \
+	settings/$(DEPDIR)/$(am__dirstamp)
+settings/settings_parser.h: settings/settings_parser.c
+	@if test ! -f $@; then rm -f settings/settings_parser.c; else :; fi
+	@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) settings/settings_parser.c; else :; fi
+settings/settings_parser.lo: settings/$(am__dirstamp) \
+	settings/$(DEPDIR)/$(am__dirstamp)
+settings/settings_lexer.lo: settings/$(am__dirstamp) \
+	settings/$(DEPDIR)/$(am__dirstamp)
 utils/$(am__dirstamp):
 	@$(MKDIR_P) utils
 	@: > utils/$(am__dirstamp)
@@ -1351,7 +1454,7 @@ utils/capabilities.lo: utils/$(am__dirstamp) \
 	utils/$(DEPDIR)/$(am__dirstamp)
 utils/backtrace.lo: utils/$(am__dirstamp) \
 	utils/$(DEPDIR)/$(am__dirstamp)
-utils/settings.lo: utils/$(am__dirstamp) \
+utils/parser_helper.lo: utils/$(am__dirstamp) \
 	utils/$(DEPDIR)/$(am__dirstamp)
 utils/test.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp)
 utils/utils/$(am__dirstamp):
@@ -1362,6 +1465,49 @@ utils/utils/$(DEPDIR)/$(am__dirstamp):
 	@: > utils/utils/$(DEPDIR)/$(am__dirstamp)
 utils/utils/strerror.lo: utils/utils/$(am__dirstamp) \
 	utils/utils/$(DEPDIR)/$(am__dirstamp)
+threading/$(am__dirstamp):
+	@$(MKDIR_P) threading
+	@: > threading/$(am__dirstamp)
+threading/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) threading/$(DEPDIR)
+	@: > threading/$(DEPDIR)/$(am__dirstamp)
+threading/thread.lo: threading/$(am__dirstamp) \
+	threading/$(DEPDIR)/$(am__dirstamp)
+threading/thread_value.lo: threading/$(am__dirstamp) \
+	threading/$(DEPDIR)/$(am__dirstamp)
+threading/mutex.lo: threading/$(am__dirstamp) \
+	threading/$(DEPDIR)/$(am__dirstamp)
+threading/rwlock.lo: threading/$(am__dirstamp) \
+	threading/$(DEPDIR)/$(am__dirstamp)
+threading/spinlock.lo: threading/$(am__dirstamp) \
+	threading/$(DEPDIR)/$(am__dirstamp)
+threading/semaphore.lo: threading/$(am__dirstamp) \
+	threading/$(DEPDIR)/$(am__dirstamp)
+networking/streams/stream_unix.lo: networking/streams/$(am__dirstamp) \
+	networking/streams/$(DEPDIR)/$(am__dirstamp)
+networking/streams/stream_service_unix.lo:  \
+	networking/streams/$(am__dirstamp) \
+	networking/streams/$(DEPDIR)/$(am__dirstamp)
+threading/windows/$(am__dirstamp):
+	@$(MKDIR_P) threading/windows
+	@: > threading/windows/$(am__dirstamp)
+threading/windows/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) threading/windows/$(DEPDIR)
+	@: > threading/windows/$(DEPDIR)/$(am__dirstamp)
+threading/windows/thread.lo: threading/windows/$(am__dirstamp) \
+	threading/windows/$(DEPDIR)/$(am__dirstamp)
+threading/windows/thread_value.lo: threading/windows/$(am__dirstamp) \
+	threading/windows/$(DEPDIR)/$(am__dirstamp)
+threading/windows/mutex.lo: threading/windows/$(am__dirstamp) \
+	threading/windows/$(DEPDIR)/$(am__dirstamp)
+threading/windows/rwlock.lo: threading/windows/$(am__dirstamp) \
+	threading/windows/$(DEPDIR)/$(am__dirstamp)
+threading/windows/spinlock.lo: threading/windows/$(am__dirstamp) \
+	threading/windows/$(DEPDIR)/$(am__dirstamp)
+threading/windows/semaphore.lo: threading/windows/$(am__dirstamp) \
+	threading/windows/$(DEPDIR)/$(am__dirstamp)
+utils/windows.lo: utils/$(am__dirstamp) \
+	utils/$(DEPDIR)/$(am__dirstamp)
 utils/leak_detective.lo: utils/$(am__dirstamp) \
 	utils/$(DEPDIR)/$(am__dirstamp)
 utils/integrity_checker.lo: utils/$(am__dirstamp) \
@@ -1443,8 +1589,12 @@ mostlyclean-compile:
 	-rm -f resolver/*.lo
 	-rm -f selectors/*.$(OBJEXT)
 	-rm -f selectors/*.lo
+	-rm -f settings/*.$(OBJEXT)
+	-rm -f settings/*.lo
 	-rm -f threading/*.$(OBJEXT)
 	-rm -f threading/*.lo
+	-rm -f threading/windows/*.$(OBJEXT)
+	-rm -f threading/windows/*.lo
 	-rm -f utils/*.$(OBJEXT)
 	-rm -f utils/*.lo
 	-rm -f utils/printf_hook/*.$(OBJEXT)
@@ -1515,6 +1665,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at networking/streams/$(DEPDIR)/stream.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at networking/streams/$(DEPDIR)/stream_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at networking/streams/$(DEPDIR)/stream_service.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at networking/streams/$(DEPDIR)/stream_service_tcp.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at networking/streams/$(DEPDIR)/stream_service_unix.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at networking/streams/$(DEPDIR)/stream_tcp.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at networking/streams/$(DEPDIR)/stream_unix.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at pen/$(DEPDIR)/pen.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/plugin_feature.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at plugins/$(DEPDIR)/plugin_loader.Plo at am__quote@
@@ -1526,12 +1680,22 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at resolver/$(DEPDIR)/resolver_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at resolver/$(DEPDIR)/rr_set.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at selectors/$(DEPDIR)/traffic_selector.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/settings.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/settings_lexer.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/settings_parser.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/settings_types.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at threading/$(DEPDIR)/mutex.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at threading/$(DEPDIR)/rwlock.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at threading/$(DEPDIR)/semaphore.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at threading/$(DEPDIR)/spinlock.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at threading/$(DEPDIR)/thread.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at threading/$(DEPDIR)/thread_value.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at threading/windows/$(DEPDIR)/mutex.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at threading/windows/$(DEPDIR)/rwlock.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at threading/windows/$(DEPDIR)/semaphore.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at threading/windows/$(DEPDIR)/spinlock.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at threading/windows/$(DEPDIR)/thread.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at threading/windows/$(DEPDIR)/thread_value.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/backtrace.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/capabilities.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/chunk.Plo at am__quote@
@@ -1542,9 +1706,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/leak_detective.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/lexparser.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/optionsfrom.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/settings.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/parser_helper.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/test.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/utils.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/windows.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/printf_hook/$(DEPDIR)/printf_hook_builtin.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/printf_hook/$(DEPDIR)/printf_hook_glibc.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/printf_hook/$(DEPDIR)/printf_hook_vstr.Plo at am__quote@
@@ -1574,6 +1739,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
+.l.c:
+	$(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+	$(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
@@ -1607,7 +1778,9 @@ clean-libtool:
 	-rm -rf processing/jobs/.libs processing/jobs/_libs
 	-rm -rf resolver/.libs resolver/_libs
 	-rm -rf selectors/.libs selectors/_libs
+	-rm -rf settings/.libs settings/_libs
 	-rm -rf threading/.libs threading/_libs
+	-rm -rf threading/windows/.libs threading/windows/_libs
 	-rm -rf utils/.libs utils/_libs
 	-rm -rf utils/printf_hook/.libs utils/printf_hook/_libs
 	-rm -rf utils/utils/.libs utils/utils/_libs
@@ -1882,8 +2055,12 @@ distclean-generic:
 	-rm -f resolver/$(am__dirstamp)
 	-rm -f selectors/$(DEPDIR)/$(am__dirstamp)
 	-rm -f selectors/$(am__dirstamp)
+	-rm -f settings/$(DEPDIR)/$(am__dirstamp)
+	-rm -f settings/$(am__dirstamp)
 	-rm -f threading/$(DEPDIR)/$(am__dirstamp)
 	-rm -f threading/$(am__dirstamp)
+	-rm -f threading/windows/$(DEPDIR)/$(am__dirstamp)
+	-rm -f threading/windows/$(am__dirstamp)
 	-rm -f utils/$(DEPDIR)/$(am__dirstamp)
 	-rm -f utils/$(am__dirstamp)
 	-rm -f utils/printf_hook/$(DEPDIR)/$(am__dirstamp)
@@ -1894,6 +2071,9 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
+	-rm -f settings/settings_lexer.c
+	-rm -f settings/settings_parser.c
+	-rm -f settings/settings_parser.h
 	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
 	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
 clean: clean-recursive
@@ -1902,7 +2082,7 @@ clean-am: clean-generic clean-ipseclibLTLIBRARIES clean-libtool \
 	mostlyclean-am
 
 distclean: distclean-recursive
-	-rm -rf ./$(DEPDIR) asn1/$(DEPDIR) bio/$(DEPDIR) collections/$(DEPDIR) credentials/$(DEPDIR) credentials/certificates/$(DEPDIR) credentials/containers/$(DEPDIR) credentials/keys/$(DEPDIR) credentials/sets/$(DEPDIR) crypto/$(DEPDIR) crypto/crypters/$(DEPDIR) crypto/hashers/$(DEPDIR) crypto/iv/$(DEPDIR) crypto/prfs/$(DEPDIR) crypto/proposal/$(DEPDIR) crypto/rngs/$(DEPDIR) crypto/signers/$(DEPDIR) database/$(DEPDIR) eap/$(DEPDIR) fetcher/$(DEPDIR) ipsec/$(DEPDIR) networking/$(DEPDIR) netwo [...]
+	-rm -rf ./$(DEPDIR) asn1/$(DEPDIR) bio/$(DEPDIR) collections/$(DEPDIR) credentials/$(DEPDIR) credentials/certificates/$(DEPDIR) credentials/containers/$(DEPDIR) credentials/keys/$(DEPDIR) credentials/sets/$(DEPDIR) crypto/$(DEPDIR) crypto/crypters/$(DEPDIR) crypto/hashers/$(DEPDIR) crypto/iv/$(DEPDIR) crypto/prfs/$(DEPDIR) crypto/proposal/$(DEPDIR) crypto/rngs/$(DEPDIR) crypto/signers/$(DEPDIR) database/$(DEPDIR) eap/$(DEPDIR) fetcher/$(DEPDIR) ipsec/$(DEPDIR) networking/$(DEPDIR) netwo [...]
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-tags
@@ -1949,7 +2129,7 @@ install-ps-am:
 installcheck-am:
 
 maintainer-clean: maintainer-clean-recursive
-	-rm -rf ./$(DEPDIR) asn1/$(DEPDIR) bio/$(DEPDIR) collections/$(DEPDIR) credentials/$(DEPDIR) credentials/certificates/$(DEPDIR) credentials/containers/$(DEPDIR) credentials/keys/$(DEPDIR) credentials/sets/$(DEPDIR) crypto/$(DEPDIR) crypto/crypters/$(DEPDIR) crypto/hashers/$(DEPDIR) crypto/iv/$(DEPDIR) crypto/prfs/$(DEPDIR) crypto/proposal/$(DEPDIR) crypto/rngs/$(DEPDIR) crypto/signers/$(DEPDIR) database/$(DEPDIR) eap/$(DEPDIR) fetcher/$(DEPDIR) ipsec/$(DEPDIR) networking/$(DEPDIR) netwo [...]
+	-rm -rf ./$(DEPDIR) asn1/$(DEPDIR) bio/$(DEPDIR) collections/$(DEPDIR) credentials/$(DEPDIR) credentials/certificates/$(DEPDIR) credentials/containers/$(DEPDIR) credentials/keys/$(DEPDIR) credentials/sets/$(DEPDIR) crypto/$(DEPDIR) crypto/crypters/$(DEPDIR) crypto/hashers/$(DEPDIR) crypto/iv/$(DEPDIR) crypto/prfs/$(DEPDIR) crypto/proposal/$(DEPDIR) crypto/rngs/$(DEPDIR) crypto/signers/$(DEPDIR) database/$(DEPDIR) eap/$(DEPDIR) fetcher/$(DEPDIR) ipsec/$(DEPDIR) networking/$(DEPDIR) netwo [...]
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 38a6ad6..05be574 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -460,7 +460,7 @@ chunk_t asn1_from_time(const time_t *time, asn1_t type)
 	const char *format;
 	char buf[BUF_LEN];
 	chunk_t formatted_time;
-	struct tm t;
+	struct tm t = {};
 
 	gmtime_r(time, &t);
 	/* RFC 5280 says that dates through the year 2049 MUST be encoded as UTCTIME
diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h
index d72d986..0933f23 100644
--- a/src/libstrongswan/asn1/oid.h
+++ b/src/libstrongswan/asn1/oid.h
@@ -5,7 +5,7 @@
  * Do not edit manually!
  */
 
-#include <sys/types.h>
+#include <utils/utils.h>
 
 #ifndef OID_H_
 #define OID_H_
diff --git a/src/libstrongswan/asn1/oid.pl b/src/libstrongswan/asn1/oid.pl
index 82100e8..c45077a 100644
--- a/src/libstrongswan/asn1/oid.pl
+++ b/src/libstrongswan/asn1/oid.pl
@@ -30,7 +30,7 @@ print OID_H "/* Object identifiers (OIDs) used by strongSwan\n",
 	    " * ", $automatic, "\n",
 	    " * ", $warning, "\n",
 	    " */\n\n",
-	    "#include <sys/types.h>\n\n",
+	    "#include <utils/utils.h>\n\n",
 	    "#ifndef OID_H_\n",
 	    "#define OID_H_\n\n",
 	    "typedef struct {\n",
diff --git a/src/libstrongswan/collections/array.c b/src/libstrongswan/collections/array.c
index 75efb85..8d61911 100644
--- a/src/libstrongswan/collections/array.c
+++ b/src/libstrongswan/collections/array.c
@@ -168,7 +168,7 @@ array_t *array_create(u_int esize, u_int8_t reserve)
 	);
 	if (array->tail)
 	{
-		array->data = malloc(array->tail * array->esize);
+		array->data = malloc(get_size(array, array->tail));
 	}
 	return array;
 }
diff --git a/src/libstrongswan/collections/dictionary.h b/src/libstrongswan/collections/dictionary.h
new file mode 100644
index 0000000..679e41d
--- /dev/null
+++ b/src/libstrongswan/collections/dictionary.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup dictionary dictionary
+ * @{ @ingroup collections
+ */
+
+#ifndef DICTIONARY_H_
+#define DICTIONARY_H_
+
+#include <collections/enumerator.h>
+
+typedef struct dictionary_t dictionary_t;
+
+/**
+ * Interface for read-only dictionaries.
+ */
+struct dictionary_t {
+
+	/**
+	 * Create an enumerator over the key/value pairs in the dictionary.
+	 *
+	 * @return			enumerator over (const void *key, void *value)
+	 */
+	enumerator_t *(*create_enumerator)(dictionary_t *this);
+
+	/**
+	 * Returns the value with the given key, if the dictionary contains such an
+	 * entry, otherwise NULL is returned.
+	 *
+	 * @param key		the key of the requested value
+	 * @return			the value, NULL if not found
+	 */
+	void *(*get)(dictionary_t *this, const void *key);
+
+	/**
+	 * Destroys a dictionary object.
+	 */
+	void (*destroy)(dictionary_t *this);
+};
+
+#endif /** DICTIONARY_H_ @}*/
diff --git a/src/libstrongswan/collections/enumerator.c b/src/libstrongswan/collections/enumerator.c
index 8049ac0..fa277e7 100644
--- a/src/libstrongswan/collections/enumerator.c
+++ b/src/libstrongswan/collections/enumerator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2013 Tobias Brunner
  * Copyright (C) 2007 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -25,6 +25,10 @@
 #include <errno.h>
 #include <string.h>
 
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif /* HAVE_GLOB_H */
+
 #include <utils/debug.h>
 
 /**
@@ -157,8 +161,103 @@ enumerator_t* enumerator_create_directory(const char *path)
 	return &this->public;
 }
 
+#ifdef HAVE_GLOB_H
+
 /**
- * Enumerator implementation for directory enumerator
+ * Enumerator implementation for glob enumerator
+ */
+typedef struct {
+	/** implements enumerator_t */
+	enumerator_t public;
+	/** glob data */
+	glob_t glob;
+	/** iteration count */
+	u_int pos;
+	/** absolute path of current file */
+	char full[PATH_MAX];
+} glob_enum_t;
+
+/**
+ * Implementation of enumerator_create_glob().destroy
+ */
+static void destroy_glob_enum(glob_enum_t *this)
+{
+	globfree(&this->glob);
+	free(this);
+}
+
+/**
+ * Implementation of enumerator_create_glob().enumerate
+ */
+static bool enumerate_glob_enum(glob_enum_t *this, char **file, struct stat *st)
+{
+	char *match;
+
+	if (this->pos >= this->glob.gl_pathc)
+	{
+		return FALSE;
+	}
+	match = this->glob.gl_pathv[this->pos++];
+	if (file)
+	{
+		*file = match;
+	}
+	if (st)
+	{
+		if (stat(match, st))
+		{
+			DBG1(DBG_LIB, "stat() on '%s' failed: %s", match,
+				 strerror(errno));
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * See header
+ */
+enumerator_t* enumerator_create_glob(const char *pattern)
+{
+	glob_enum_t *this;
+	int status;
+
+	if (!pattern)
+	{
+		return enumerator_create_empty();
+	}
+
+	INIT(this,
+		.public = {
+			.enumerate = (void*)enumerate_glob_enum,
+			.destroy = (void*)destroy_glob_enum,
+		},
+	);
+
+	status = glob(pattern, GLOB_ERR, NULL, &this->glob);
+	if (status == GLOB_NOMATCH)
+	{
+		DBG1(DBG_LIB, "no files found matching '%s'", pattern);
+	}
+	else if (status != 0)
+	{
+		DBG1(DBG_LIB, "expanding file pattern '%s' failed: %s", pattern,
+			 strerror(errno));
+	}
+	return &this->public;
+}
+
+#else /* HAVE_GLOB_H */
+
+enumerator_t* enumerator_create_glob(const char *pattern)
+{
+	return NULL;
+}
+
+#endif /* HAVE_GLOB_H */
+
+/**
+ * Enumerator implementation for token enumerator
  */
 typedef struct {
 	/** implements enumerator_t */
diff --git a/src/libstrongswan/collections/enumerator.h b/src/libstrongswan/collections/enumerator.h
index 299373a..55f8d83 100644
--- a/src/libstrongswan/collections/enumerator.h
+++ b/src/libstrongswan/collections/enumerator.h
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2013 Tobias Brunner
  * Copyright (C) 2007 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -69,7 +70,9 @@ enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item));
  * This enumerator_t.enumerate() function returns a (to the directory) relative
  * filename (as a char*), an absolute filename (as a char*) and a file status
  * (to a struct stat), which all may be NULL. "." and ".." entries are
- * skipped. Example:
+ * skipped.
+ *
+ * Example:
  *
  * @code
 	char *rel, *abs;
@@ -96,6 +99,38 @@ enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item));
 enumerator_t* enumerator_create_directory(const char *path);
 
 /**
+ * Create an enumerator over files/directories matching a file pattern.
+ *
+ * This enumerator_t.enumerate() function returns the filename (as a char*),
+ * and a file status (to a struct stat), which both may be NULL.
+ *
+ * Example:
+ *
+ * @code
+	char *file;
+	struct stat st;
+	enumerator_t *e;
+
+	e = enumerator_create_glob("/etc/ipsec.*.conf");
+	if (e)
+	{
+		while (e->enumerate(e, &file, &st))
+		{
+			if (S_ISREG(st.st_mode))
+			{
+				printf("%s\n", file);
+			}
+		}
+		e->destroy(e);
+	}
+   @endcode
+ *
+ * @param pattern	file pattern to match
+ * @return 			the enumerator, NULL if not supported
+ */
+enumerator_t* enumerator_create_glob(const char *pattern);
+
+/**
  * Create an enumerator over tokens of a string.
  *
  * Tokens are separated by one of the characters in sep and trimmed by the
diff --git a/src/libstrongswan/collections/hashtable.c b/src/libstrongswan/collections/hashtable.c
index ca31d83..2b77a37 100644
--- a/src/libstrongswan/collections/hashtable.c
+++ b/src/libstrongswan/collections/hashtable.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008-2014 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -250,7 +250,7 @@ static void rehash(private_hashtable_t *this)
 }
 
 METHOD(hashtable_t, put, void*,
-	   private_hashtable_t *this, const void *key, void *value)
+	private_hashtable_t *this, const void *key, void *value)
 {
 	void *old_value = NULL;
 	pair_t *pair;
@@ -309,19 +309,19 @@ static void *get_internal(private_hashtable_t *this, const void *key,
 }
 
 METHOD(hashtable_t, get, void*,
-	   private_hashtable_t *this, const void *key)
+	private_hashtable_t *this, const void *key)
 {
 	return get_internal(this, key, this->equals);
 }
 
 METHOD(hashtable_t, get_match, void*,
-	   private_hashtable_t *this, const void *key, hashtable_equals_t match)
+	private_hashtable_t *this, const void *key, hashtable_equals_t match)
 {
 	return get_internal(this, key, match);
 }
 
 METHOD(hashtable_t, remove_, void*,
-	   private_hashtable_t *this, const void *key)
+	private_hashtable_t *this, const void *key)
 {
 	void *value = NULL;
 	pair_t *pair, *prev = NULL;
@@ -353,7 +353,7 @@ METHOD(hashtable_t, remove_, void*,
 }
 
 METHOD(hashtable_t, remove_at, void,
-	   private_hashtable_t *this, private_enumerator_t *enumerator)
+	private_hashtable_t *this, private_enumerator_t *enumerator)
 {
 	if (enumerator->table == this && enumerator->current)
 	{
@@ -373,13 +373,13 @@ METHOD(hashtable_t, remove_at, void,
 }
 
 METHOD(hashtable_t, get_count, u_int,
-	   private_hashtable_t *this)
+	private_hashtable_t *this)
 {
 	return this->count;
 }
 
 METHOD(enumerator_t, enumerate, bool,
-	   private_enumerator_t *this, const void **key, void **value)
+	private_enumerator_t *this, const void **key, void **value)
 {
 	while (this->count && this->row < this->table->capacity)
 	{
@@ -411,7 +411,7 @@ METHOD(enumerator_t, enumerate, bool,
 }
 
 METHOD(hashtable_t, create_enumerator, enumerator_t*,
-	   private_hashtable_t *this)
+	private_hashtable_t *this)
 {
 	private_enumerator_t *enumerator;
 
@@ -427,8 +427,8 @@ METHOD(hashtable_t, create_enumerator, enumerator_t*,
 	return &enumerator->enumerator;
 }
 
-METHOD(hashtable_t, destroy, void,
-	   private_hashtable_t *this)
+static void destroy_internal(private_hashtable_t *this,
+							 void (*fn)(void*,const void*))
 {
 	pair_t *pair, *next;
 	u_int row;
@@ -438,6 +438,10 @@ METHOD(hashtable_t, destroy, void,
 		pair = this->table[row];
 		while (pair)
 		{
+			if (fn)
+			{
+				fn(pair->value, pair->key);
+			}
 			next = pair->next;
 			free(pair);
 			pair = next;
@@ -447,6 +451,18 @@ METHOD(hashtable_t, destroy, void,
 	free(this);
 }
 
+METHOD(hashtable_t, destroy, void,
+	private_hashtable_t *this)
+{
+	destroy_internal(this, NULL);
+}
+
+METHOD(hashtable_t, destroy_function, void,
+	private_hashtable_t *this, void (*fn)(void*,const void*))
+{
+	destroy_internal(this, fn);
+}
+
 /*
  * Described in header.
  */
@@ -465,6 +481,7 @@ hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
 			.get_count = _get_count,
 			.create_enumerator = _create_enumerator,
 			.destroy = _destroy,
+			.destroy_function = _destroy_function,
 		},
 		.hash = hash,
 		.equals = equals,
diff --git a/src/libstrongswan/collections/hashtable.h b/src/libstrongswan/collections/hashtable.h
index 0a7ebeb..f60564a 100644
--- a/src/libstrongswan/collections/hashtable.h
+++ b/src/libstrongswan/collections/hashtable.h
@@ -156,6 +156,15 @@ struct hashtable_t {
 	 * Destroys a hash table object.
 	 */
 	void (*destroy) (hashtable_t *this);
+
+	/**
+	 * Destroys a hash table object and calls the given function for each
+	 * item and its key in the hash table.
+	 *
+	 * @param function	function to call on each item and key
+	 */
+	void (*destroy_function)(hashtable_t *this,
+							 void (*)(void *val, const void *key));
 };
 
 /**
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
index 4ff9aa6..aeeb419 100644
--- a/src/libstrongswan/credentials/auth_cfg.c
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -452,7 +452,7 @@ METHOD(auth_cfg_t, get, void*,
 		case AUTH_RULE_ECDSA_STRENGTH:
 			return (void*)0;
 		case AUTH_RULE_SIGNATURE_SCHEME:
-			return HASH_UNKNOWN;
+			return (void*)HASH_UNKNOWN;
 		case AUTH_RULE_CRL_VALIDATION:
 		case AUTH_RULE_OCSP_VALIDATION:
 			return (void*)VALIDATION_FAILED;
diff --git a/src/libstrongswan/credentials/certificates/crl.h b/src/libstrongswan/credentials/certificates/crl.h
index 4191c59..8a48bd7 100644
--- a/src/libstrongswan/credentials/certificates/crl.h
+++ b/src/libstrongswan/credentials/certificates/crl.h
@@ -28,18 +28,30 @@ typedef enum crl_reason_t crl_reason_t;
 #include <library.h>
 #include <credentials/certificates/certificate.h>
 
+/* <wincrypt.h> comes with CRL_REASON clashing with ours. Even if the values
+ * are identical, we undef them here to use our enum instead of defines. */
+#ifdef WIN32
+# undef CRL_REASON_UNSPECIFIED
+# undef CRL_REASON_KEY_COMPROMISE
+# undef CRL_REASON_CA_COMPROMISE
+# undef CRL_REASON_AFFILIATION_CHANGED
+# undef CRL_REASON_SUPERSEDED
+# undef CRL_REASON_CERTIFICATE_HOLD
+# undef CRL_REASON_REMOVE_FROM_CRL
+#endif
+
 /**
  * RFC 2459 CRL reason codes
  */
 enum crl_reason_t {
-	CRL_REASON_UNSPECIFIED			= 0,
-	CRL_REASON_KEY_COMPROMISE		 = 1,
-	CRL_REASON_CA_COMPROMISE		  = 2,
-	CRL_REASON_AFFILIATION_CHANGED	= 3,
-	CRL_REASON_SUPERSEDED			 = 4,
-	CRL_REASON_CESSATION_OF_OPERATON  = 5,
-	CRL_REASON_CERTIFICATE_HOLD	   = 6,
-	CRL_REASON_REMOVE_FROM_CRL		= 8,
+	CRL_REASON_UNSPECIFIED				= 0,
+	CRL_REASON_KEY_COMPROMISE			= 1,
+	CRL_REASON_CA_COMPROMISE			= 2,
+	CRL_REASON_AFFILIATION_CHANGED		= 3,
+	CRL_REASON_SUPERSEDED				= 4,
+	CRL_REASON_CESSATION_OF_OPERATON	= 5,
+	CRL_REASON_CERTIFICATE_HOLD			= 6,
+	CRL_REASON_REMOVE_FROM_CRL			= 8,
 };
 
 /**
diff --git a/src/libstrongswan/credentials/cred_encoding.h b/src/libstrongswan/credentials/cred_encoding.h
index 27a887f..a6c9c30 100644
--- a/src/libstrongswan/credentials/cred_encoding.h
+++ b/src/libstrongswan/credentials/cred_encoding.h
@@ -89,6 +89,8 @@ enum cred_encoding_type_t {
 	PUBKEY_DNSKEY,
 	/** SSHKEY encoding (Base64) */
 	PUBKEY_SSHKEY,
+	/** RSA modulus only */
+	PUBKEY_RSA_MODULUS,
 
 	/** ASN.1 DER encoded certificate */
 	CERT_ASN1_DER,
diff --git a/src/libstrongswan/credentials/sets/cert_cache.c b/src/libstrongswan/credentials/sets/cert_cache.c
index e8f0e7e..563f4bd 100644
--- a/src/libstrongswan/credentials/sets/cert_cache.c
+++ b/src/libstrongswan/credentials/sets/cert_cache.c
@@ -16,7 +16,6 @@
 #include "cert_cache.h"
 
 #include <time.h>
-#include <sched.h>
 
 #include <library.h>
 #include <threading/rwlock.h>
diff --git a/src/libstrongswan/credentials/sets/mem_cred.c b/src/libstrongswan/credentials/sets/mem_cred.c
index b8da3f6..d8f568d 100644
--- a/src/libstrongswan/credentials/sets/mem_cred.c
+++ b/src/libstrongswan/credentials/sets/mem_cred.c
@@ -307,8 +307,25 @@ METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
 METHOD(mem_cred_t, add_key, void,
 	private_mem_cred_t *this, private_key_t *key)
 {
+	enumerator_t *enumerator;
+	private_key_t *current;
+
 	this->lock->write_lock(this->lock);
+
+	enumerator = this->keys->create_enumerator(this->keys);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (current->equals(current, key))
+		{
+			this->keys->remove_at(this->keys, enumerator);
+			current->destroy(current);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
 	this->keys->insert_first(this->keys, key);
+
 	this->lock->unlock(this->lock);
 }
 
@@ -334,6 +351,44 @@ static void shared_entry_destroy(shared_entry_t *entry)
 }
 
 /**
+ * Check if two shared key entries equal
+ */
+static bool shared_entry_equals(shared_entry_t *a, shared_entry_t *b)
+{
+	enumerator_t *e1, *e2;
+	identification_t *id1, *id2;
+	bool equals = TRUE;
+
+	if (a->shared->get_type(a->shared) != b->shared->get_type(b->shared))
+	{
+		return FALSE;
+	}
+	if (!chunk_equals(a->shared->get_key(a->shared),
+					  b->shared->get_key(b->shared)))
+	{
+		return FALSE;
+	}
+	if (a->owners->get_count(a->owners) != b->owners->get_count(b->owners))
+	{
+		return FALSE;
+	}
+	e1 = a->owners->create_enumerator(a->owners);
+	e2 = b->owners->create_enumerator(b->owners);
+	while (e1->enumerate(e1, &id1) && e2->enumerate(e2, &id2))
+	{
+		if (!id1->equals(id1, id2))
+		{
+			equals = FALSE;
+			break;
+		}
+	}
+	e1->destroy(e1);
+	e2->destroy(e2);
+
+	return equals;
+}
+
+/**
  * Data for the shared_key enumerator
  */
 typedef struct {
@@ -435,15 +490,30 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
 METHOD(mem_cred_t, add_shared_list, void,
 	private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners)
 {
-	shared_entry_t *entry;
+	shared_entry_t *current, *new;
+	enumerator_t *enumerator;
 
-	INIT(entry,
+	INIT(new,
 		.shared = shared,
 		.owners = owners,
 	);
 
 	this->lock->write_lock(this->lock);
-	this->shared->insert_first(this->shared, entry);
+
+	enumerator = this->shared->create_enumerator(this->shared);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (shared_entry_equals(current, new))
+		{
+			this->shared->remove_at(this->shared, enumerator);
+			shared_entry_destroy(current);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	this->shared->insert_first(this->shared, new);
+
 	this->lock->unlock(this->lock);
 }
 
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c
index 6dea30e..96fbc0d 100644
--- a/src/libstrongswan/crypto/crypto_factory.c
+++ b/src/libstrongswan/crypto/crypto_factory.c
@@ -392,10 +392,10 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
 /**
  * Insert an algorithm entry to a list
  *
- * Entries are sorted by algorithm identifier (which is important for RNGs)
- * while maintaining the order in which algorithms were added, unless they were
+ * Entries maintain the order in which algorithms were added, unless they were
  * benchmarked and speed is provided, which then is used to order entries of
  * the same algorithm.
+ * An exception are RNG entries, which are sorted by algorithm identifier.
  */
 static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
 					  int algo, const char *plugin_name,
@@ -403,6 +403,7 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
 {
 	enumerator_t *enumerator;
 	entry_t *entry, *current;
+	bool sort = (list == this->rngs), found = FALSE;
 
 	INIT(entry,
 		.algo = algo,
@@ -415,12 +416,19 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
 	enumerator = list->create_enumerator(list);
 	while (enumerator->enumerate(enumerator, &current))
 	{
-		if (current->algo > algo)
+		if (sort && current->algo > algo)
 		{
 			break;
 		}
-		else if (current->algo == algo && speed &&
-				 current->speed < speed)
+		else if (current->algo == algo)
+		{
+			if (speed > current->speed)
+			{
+				break;
+			}
+			found = TRUE;
+		}
+		else if (found)
 		{
 			break;
 		}
diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c
index c6780da..d09844b 100644
--- a/src/libstrongswan/crypto/crypto_tester.c
+++ b/src/libstrongswan/crypto/crypto_tester.c
@@ -14,8 +14,10 @@
  * for more details.
  */
 
-#define _GNU_SOURCE
-#include <dlfcn.h>
+#ifdef HAVE_DLADDR
+# define _GNU_SOURCE
+# include <dlfcn.h>
+#endif
 #include <time.h>
 
 #include "crypto_tester.h"
@@ -102,7 +104,7 @@ static const char* get_name(void *sym)
 	return "unknown";
 }
 
-#ifdef CLOCK_THREAD_CPUTIME_ID
+#if defined(CLOCK_THREAD_CPUTIME_ID) && defined(HAVE_CLOCK_GETTIME)
 
 /**
  * Start a benchmark timer
diff --git a/src/libstrongswan/crypto/transform.h b/src/libstrongswan/crypto/transform.h
index 4a98f81..a585e97 100644
--- a/src/libstrongswan/crypto/transform.h
+++ b/src/libstrongswan/crypto/transform.h
@@ -23,7 +23,7 @@
 
 typedef enum transform_type_t transform_type_t;
 
-#include <utils/enum.h>
+#include <utils/utils.h>
 
 /**
  * Type of a transform, as in IKEv2 RFC 3.3.2.
diff --git a/src/libstrongswan/eap/eap.c b/src/libstrongswan/eap/eap.c
index c181c5d..64b5dbe 100644
--- a/src/libstrongswan/eap/eap.c
+++ b/src/libstrongswan/eap/eap.c
@@ -57,7 +57,9 @@ ENUM_NEXT(eap_type_names, EAP_MSTLV, EAP_MSTLV, EAP_MSCHAPV2,
 	"EAP_MSTLV");
 ENUM_NEXT(eap_type_names, EAP_TNC, EAP_TNC, EAP_MSTLV,
 	"EAP_TNC");
-ENUM_NEXT(eap_type_names, EAP_EXPANDED, EAP_DYNAMIC, EAP_TNC,
+ENUM_NEXT(eap_type_names, EAP_PT_EAP, EAP_PT_EAP, EAP_TNC,
+	"EAP_PT_EAP");
+ENUM_NEXT(eap_type_names, EAP_EXPANDED, EAP_DYNAMIC, EAP_PT_EAP,
 	"EAP_EXPANDED",
 	"EAP_EXPERIMENTAL",
 	"EAP_RADIUS",
@@ -86,7 +88,9 @@ ENUM_NEXT(eap_type_short_names, EAP_MSTLV, EAP_MSTLV, EAP_MSCHAPV2,
 	"MSTLV");
 ENUM_NEXT(eap_type_short_names, EAP_TNC, EAP_TNC, EAP_MSTLV,
 	"TNC");
-ENUM_NEXT(eap_type_short_names, EAP_EXPANDED, EAP_DYNAMIC, EAP_TNC,
+ENUM_NEXT(eap_type_short_names, EAP_PT_EAP, EAP_PT_EAP, EAP_TNC,
+	"PT");
+ENUM_NEXT(eap_type_short_names, EAP_EXPANDED, EAP_DYNAMIC, EAP_PT_EAP,
 	"EXP",
 	"XP",
 	"RAD",
@@ -114,6 +118,7 @@ eap_type_t eap_type_from_string(char *name)
 		{"peap",		EAP_PEAP},
 		{"mschapv2",	EAP_MSCHAPV2},
 		{"tnc",			EAP_TNC},
+		{"pt",			EAP_PT_EAP},
 		{"dynamic",		EAP_DYNAMIC},
 		{"radius",		EAP_RADIUS},
 	};
@@ -136,7 +141,7 @@ eap_vendor_type_t *eap_vendor_type_from_string(char *str)
 	enumerator_t *enumerator;
 	eap_vendor_type_t *result = NULL;
 	eap_type_t type = 0;
-	u_int32_t vendor = 0;
+	uint32_t vendor = 0;
 	char *part, *end;
 
 	/* parse EAP method string of the form: [eap-]type[-vendor] */
diff --git a/src/libstrongswan/eap/eap.h b/src/libstrongswan/eap/eap.h
index 0e144b1..08d88ba 100644
--- a/src/libstrongswan/eap/eap.h
+++ b/src/libstrongswan/eap/eap.h
@@ -67,6 +67,7 @@ enum eap_type_t {
 	EAP_MSCHAPV2 = 26,
 	EAP_MSTLV = 33,
 	EAP_TNC = 38,
+	EAP_PT_EAP = 54,
 	EAP_EXPANDED = 254,
 	EAP_EXPERIMENTAL = 255,
 	/** not a method, but an implementation providing different methods */
diff --git a/src/libstrongswan/fetcher/fetcher.h b/src/libstrongswan/fetcher/fetcher.h
index 890258c..6043dac 100644
--- a/src/libstrongswan/fetcher/fetcher.h
+++ b/src/libstrongswan/fetcher/fetcher.h
@@ -82,6 +82,12 @@ enum fetcher_option_t {
 	FETCH_TIMEOUT,
 
 	/**
+	 * Sets a pointer to a variable that receives the request's response code.
+	 * Additional argument is a u_int*.
+	 */
+	FETCH_RESPONSE_CODE,
+
+	/**
 	 * Callback to invoke with each chunk of data.
 	 * Additional argument fetch_callback_t.
 	 * If this option is not given, the fetcher_default_callback is used,
diff --git a/src/libstrongswan/fetcher/fetcher_manager.c b/src/libstrongswan/fetcher/fetcher_manager.c
index 2fad486..f36cfcf 100644
--- a/src/libstrongswan/fetcher/fetcher_manager.c
+++ b/src/libstrongswan/fetcher/fetcher_manager.c
@@ -113,6 +113,10 @@ METHOD(fetcher_manager_t, fetch, status_t,
 					good = fetcher->set_option(fetcher, opt,
 											va_arg(args, fetcher_callback_t));
 					continue;
+				case FETCH_RESPONSE_CODE:
+					good = fetcher->set_option(fetcher, opt,
+											va_arg(args, u_int*));
+					continue;
 				case FETCH_SOURCEIP:
 					host = va_arg(args, host_t*);
 					if (host && !host->is_anyaddr(host))
diff --git a/src/libstrongswan/ipsec/ipsec_types.h b/src/libstrongswan/ipsec/ipsec_types.h
index 6851f91..c1465e0 100644
--- a/src/libstrongswan/ipsec/ipsec_types.h
+++ b/src/libstrongswan/ipsec/ipsec_types.h
@@ -90,7 +90,9 @@ enum policy_type_t {
  * High-level priority of a policy.
  */
 enum policy_priority_t {
-	/** Default priority */
+	/** Priority for passthrough policies */
+	POLICY_PRIORITY_PASS,
+	/** Priority for regular IPsec policies */
 	POLICY_PRIORITY_DEFAULT,
 	/** Priority for trap policies */
 	POLICY_PRIORITY_ROUTED,
@@ -122,6 +124,8 @@ struct ipsec_sa_cfg_t {
 	ipsec_mode_t mode;
 	/** unique ID */
 	u_int32_t reqid;
+	/** number of policies of the same kind (in/out/fwd) attached to SA */
+	u_int32_t policy_count;
 	/** details about ESP/AH */
 	struct {
 		/** TRUE if this protocol is used */
diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c
index c5bb4cd..e3ad164 100644
--- a/src/libstrongswan/library.c
+++ b/src/libstrongswan/library.c
@@ -141,11 +141,13 @@ void library_deinit()
 	{
 		lib->leak_detective->report(lib->leak_detective, detailed);
 		lib->leak_detective->destroy(lib->leak_detective);
+		lib->leak_detective = NULL;
 	}
 
+	backtrace_deinit();
 	arrays_deinit();
+	utils_deinit();
 	threads_deinit();
-	backtrace_deinit();
 
 	free((void*)this->public.ns);
 	free(this);
@@ -249,6 +251,8 @@ bool library_init(char *settings, const char *namespace)
 		return !this->integrity_failed;
 	}
 
+	chunk_hash_seed();
+
 	INIT(this,
 		.public = {
 			.get = _get,
@@ -259,9 +263,10 @@ bool library_init(char *settings, const char *namespace)
 	);
 	lib = &this->public;
 
-	backtrace_init();
 	threads_init();
+	utils_init();
 	arrays_init();
+	backtrace_init();
 
 #ifdef LEAK_DETECTIVE
 	lib->leak_detective = leak_detective_create();
@@ -298,6 +303,13 @@ bool library_init(char *settings, const char *namespace)
 
 	this->objects = hashtable_create((hashtable_hash_t)hash,
 									 (hashtable_equals_t)equals, 4);
+
+#ifdef STRONGSWAN_CONF
+	if (!settings)
+	{
+		settings = STRONGSWAN_CONF;
+	}
+#endif
 	this->public.settings = settings_create(settings);
 	/* 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 4125328..37a83fa 100644
--- a/src/libstrongswan/library.h
+++ b/src/libstrongswan/library.h
@@ -113,8 +113,8 @@
 #include "utils/capabilities.h"
 #include "utils/integrity_checker.h"
 #include "utils/leak_detective.h"
-#include "utils/settings.h"
 #include "plugins/plugin_loader.h"
+#include "settings/settings.h"
 
 typedef struct library_t library_t;
 
diff --git a/src/libstrongswan/networking/host.h b/src/libstrongswan/networking/host.h
index 4fc6cf3..9c9b503 100644
--- a/src/libstrongswan/networking/host.h
+++ b/src/libstrongswan/networking/host.h
@@ -30,10 +30,8 @@ typedef struct host_t host_t;
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 
+#include <utils/utils.h>
 #include <utils/chunk.h>
 
 /**
diff --git a/src/libstrongswan/networking/host_resolver.c b/src/libstrongswan/networking/host_resolver.c
index 10af11a..a7524ac 100644
--- a/src/libstrongswan/networking/host_resolver.c
+++ b/src/libstrongswan/networking/host_resolver.c
@@ -14,8 +14,6 @@
  */
 
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
 
 #include "host_resolver.h"
 
diff --git a/src/libstrongswan/networking/streams/stream.c b/src/libstrongswan/networking/streams/stream.c
index f6fec0b..e49c35a 100644
--- a/src/libstrongswan/networking/streams/stream.c
+++ b/src/libstrongswan/networking/streams/stream.c
@@ -16,7 +16,8 @@
 #include <library.h>
 #include <errno.h>
 #include <unistd.h>
-#include <limits.h>
+
+#include "stream.h"
 
 typedef struct private_stream_t private_stream_t;
 
@@ -65,7 +66,7 @@ METHOD(stream_t, read_, ssize_t,
 
 		if (block)
 		{
-			ret = read(this->fd, buf, len);
+			ret = recv(this->fd, buf, len, 0);
 		}
 		else
 		{
@@ -116,7 +117,7 @@ METHOD(stream_t, write_, ssize_t,
 	{
 		if (block)
 		{
-			ret = write(this->fd, buf, len);
+			ret = send(this->fd, buf, len, 0);
 		}
 		else
 		{
@@ -287,129 +288,3 @@ stream_t *stream_create_from_fd(int fd)
 
 	return &this->public;
 }
-
-/**
- * See header
- */
-int stream_parse_uri_unix(char *uri, struct sockaddr_un *addr)
-{
-	if (!strpfx(uri, "unix://"))
-	{
-		return -1;
-	}
-	uri += strlen("unix://");
-
-	memset(addr, 0, sizeof(*addr));
-	addr->sun_family = AF_UNIX;
-	strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
-	addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
-
-	return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
-}
-
-/**
- * See header
- */
-stream_t *stream_create_unix(char *uri)
-{
-	struct sockaddr_un addr;
-	int len, fd;
-
-	len = stream_parse_uri_unix(uri, &addr);
-	if (len == -1)
-	{
-		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
-		return NULL;
-	}
-	fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (fd < 0)
-	{
-		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
-		return NULL;
-	}
-	if (connect(fd, (struct sockaddr*)&addr, len) < 0)
-	{
-		DBG1(DBG_NET, "connecting to '%s' failed: %s", uri, strerror(errno));
-		close(fd);
-		return NULL;
-	}
-	return stream_create_from_fd(fd);
-}
-
-/**
- * See header.
- */
-int stream_parse_uri_tcp(char *uri, struct sockaddr *addr)
-{
-	char *pos, buf[128];
-	host_t *host;
-	u_long port;
-	int len;
-
-	if (!strpfx(uri, "tcp://"))
-	{
-		return -1;
-	}
-	uri += strlen("tcp://");
-	pos = strrchr(uri, ':');
-	if (!pos)
-	{
-		return -1;
-	}
-	if (*uri == '[' && pos > uri && *(pos - 1) == ']')
-	{
-		/* IPv6 URI */
-		snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri - 2), uri + 1);
-	}
-	else
-	{
-		snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri), uri);
-	}
-	port = strtoul(pos + 1, &pos, 10);
-	if (port == ULONG_MAX || *pos || port > 65535)
-	{
-		return -1;
-	}
-	host = host_create_from_dns(buf, AF_UNSPEC, port);
-	if (!host)
-	{
-		return -1;
-	}
-	len = *host->get_sockaddr_len(host);
-	memcpy(addr, host->get_sockaddr(host), len);
-	host->destroy(host);
-	return len;
-}
-
-/**
- * See header
- */
-stream_t *stream_create_tcp(char *uri)
-{
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-		struct sockaddr sa;
-	} addr;
-	int fd, len;
-
-	len = stream_parse_uri_tcp(uri, &addr.sa);
-	if (len == -1)
-	{
-		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
-		return NULL;
-	}
-	fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
-	if (fd < 0)
-	{
-		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
-		return NULL;
-	}
-	if (connect(fd, &addr.sa, len))
-	{
-		DBG1(DBG_NET, "connecting to '%s' failed: %s", uri, strerror(errno));
-		close(fd);
-		return NULL;
-	}
-	return stream_create_from_fd(fd);
-}
diff --git a/src/libstrongswan/networking/streams/stream.h b/src/libstrongswan/networking/streams/stream.h
index 3516d91..747bf65 100644
--- a/src/libstrongswan/networking/streams/stream.h
+++ b/src/libstrongswan/networking/streams/stream.h
@@ -25,9 +25,6 @@ typedef struct stream_t stream_t;
 
 #include <library.h>
 
-#include <sys/un.h>
-#include <sys/socket.h>
-
 /**
  * Constructor function prototype for stream_t.
  *
@@ -138,54 +135,6 @@ struct stream_t {
 };
 
 /**
- * Create a stream for UNIX sockets.
- *
- * UNIX URIs start with unix://, followed by the socket path. For absolute
- * paths, an URI looks something like:
- *
- *   unix:///path/to/socket
- *
- * @param uri		UNIX socket specific URI, must start with "unix://"
- * @return			stream instance, NULL on failure
- */
-stream_t *stream_create_unix(char *uri);
-
-/**
- * Helper function to parse a unix:// URI to a sockaddr
- *
- * @param uri		URI
- * @param addr		sockaddr
- * @return			length of sockaddr, -1 on error
- */
-int stream_parse_uri_unix(char *uri, struct sockaddr_un *addr);
-
-/**
- * Create a stream for TCP sockets.
- *
- * TCP URIs start with tcp://, followed by a hostname (FQDN or IP), followed
- * by a colon separated port. A full TCP uri looks something like:
- *
- *   tcp://srv.example.com:5555
- *   tcp://0.0.0.0:1234
- *   tcp://[fec2::1]:7654
- *
- * There is no default port, so a colon after tcp:// is mandatory.
- *
- * @param uri		TCP socket specific URI, must start with "tcp://"
- * @return			stream instance, NULL on failure
- */
-stream_t *stream_create_tcp(char *uri);
-
-/**
- * Helper function to parse a tcp:// URI to a sockaddr
- *
- * @param uri		URI
- * @param addr		sockaddr, large enough for URI
- * @return			length of sockaddr, -1 on error
- */
-int stream_parse_uri_tcp(char *uri, struct sockaddr *addr);
-
-/**
  * Create a stream from a file descriptor.
  *
  * The file descriptor MUST be a socket for non-blocking operation.
diff --git a/src/libstrongswan/networking/streams/stream_manager.c b/src/libstrongswan/networking/streams/stream_manager.c
index 2cbd612..8de243d 100644
--- a/src/libstrongswan/networking/streams/stream_manager.c
+++ b/src/libstrongswan/networking/streams/stream_manager.c
@@ -15,6 +15,13 @@
 
 #include "stream_manager.h"
 
+#include "stream_tcp.h"
+#include "stream_service_tcp.h"
+#ifndef WIN32
+# include "stream_unix.h"
+# include "stream_service_unix.h"
+#endif
+
 #include <threading/rwlock.h>
 
 typedef struct private_stream_manager_t private_stream_manager_t;
@@ -193,10 +200,12 @@ METHOD(stream_manager_t, remove_service, void,
 METHOD(stream_manager_t, destroy, void,
 	private_stream_manager_t *this)
 {
-	remove_stream(this, stream_create_unix);
 	remove_stream(this, stream_create_tcp);
-	remove_service(this, stream_service_create_unix);
 	remove_service(this, stream_service_create_tcp);
+#ifndef WIN32
+	remove_stream(this, stream_create_unix);
+	remove_service(this, stream_service_create_unix);
+#endif
 
 	this->streams->destroy(this->streams);
 	this->services->destroy(this->services);
@@ -226,10 +235,12 @@ stream_manager_t *stream_manager_create()
 		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
 	);
 
-	add_stream(this, "unix://", stream_create_unix);
 	add_stream(this, "tcp://", stream_create_tcp);
-	add_service(this, "unix://", stream_service_create_unix);
 	add_service(this, "tcp://", stream_service_create_tcp);
+#ifndef WIN32
+	add_stream(this, "unix://", stream_create_unix);
+	add_service(this, "unix://", stream_service_create_unix);
+#endif
 
 	return &this->public;
 }
diff --git a/src/libstrongswan/networking/streams/stream_service.c b/src/libstrongswan/networking/streams/stream_service.c
index 4e0eebd..7358c58 100644
--- a/src/libstrongswan/networking/streams/stream_service.c
+++ b/src/libstrongswan/networking/streams/stream_service.c
@@ -19,10 +19,10 @@
 #include <threading/condvar.h>
 #include <processing/jobs/callback_job.h>
 
+#include "stream_service.h"
+
 #include <errno.h>
 #include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
 #include <sys/stat.h>
 
 typedef struct private_stream_service_t private_stream_service_t;
@@ -235,98 +235,3 @@ stream_service_t *stream_service_create_from_fd(int fd)
 
 	return &this->public;
 }
-
-/**
- * See header
- */
-stream_service_t *stream_service_create_unix(char *uri, int backlog)
-{
-	struct sockaddr_un addr;
-	mode_t old;
-	int fd, len;
-
-	len = stream_parse_uri_unix(uri, &addr);
-	if (len == -1)
-	{
-		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
-		return NULL;
-	}
-	if (!lib->caps->check(lib->caps, CAP_CHOWN))
-	{	/* required to chown(2) service socket */
-		DBG1(DBG_NET, "socket '%s' requires CAP_CHOWN capability", uri);
-		return NULL;
-	}
-	fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (fd == -1)
-	{
-		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
-		return NULL;
-	}
-	unlink(addr.sun_path);
-
-	old = umask(S_IRWXO);
-	if (bind(fd, (struct sockaddr*)&addr, len) < 0)
-	{
-		DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno));
-		close(fd);
-		return NULL;
-	}
-	umask(old);
-	if (chown(addr.sun_path, lib->caps->get_uid(lib->caps),
-			  lib->caps->get_gid(lib->caps)) != 0)
-	{
-		DBG1(DBG_NET, "changing socket permissions for '%s' failed: %s",
-			 uri, strerror(errno));
-	}
-	if (listen(fd, backlog) < 0)
-	{
-		DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno));
-		unlink(addr.sun_path);
-		close(fd);
-		return NULL;
-	}
-	return stream_service_create_from_fd(fd);
-}
-
-/**
- * See header
- */
-stream_service_t *stream_service_create_tcp(char *uri, int backlog)
-{
-	union {
-		struct sockaddr_in in;
-		struct sockaddr_in6 in6;
-		struct sockaddr sa;
-	} addr;
-	int fd, len, on = 1;
-
-	len = stream_parse_uri_tcp(uri, &addr.sa);
-	if (len == -1)
-	{
-		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
-		return NULL;
-	}
-	fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
-	if (fd < 0)
-	{
-		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
-		return NULL;
-	}
-	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0)
-	{
-		DBG1(DBG_NET, "SO_REUSADDR on '%s' failed: %s", uri, strerror(errno));
-	}
-	if (bind(fd, &addr.sa, len) < 0)
-	{
-		DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno));
-		close(fd);
-		return NULL;
-	}
-	if (listen(fd, backlog) < 0)
-	{
-		DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno));
-		close(fd);
-		return NULL;
-	}
-	return stream_service_create_from_fd(fd);
-}
diff --git a/src/libstrongswan/networking/streams/stream_service.h b/src/libstrongswan/networking/streams/stream_service.h
index c8faba3..de2aaf7 100644
--- a/src/libstrongswan/networking/streams/stream_service.h
+++ b/src/libstrongswan/networking/streams/stream_service.h
@@ -23,7 +23,6 @@
 
 typedef struct stream_service_t stream_service_t;
 
-#include <library.h>
 #include <processing/jobs/job.h>
 #include <networking/streams/stream.h>
 
@@ -83,22 +82,4 @@ struct stream_service_t {
  */
 stream_service_t *stream_service_create_from_fd(int fd);
 
-/**
- * Create a service instance for UNIX sockets.
- *
- * @param uri		UNIX socket specific URI, must start with "unix://"
- * @param backlog	size of the backlog queue, as passed to listen()
- * @return			stream_service instance, NULL on failure
- */
-stream_service_t *stream_service_create_unix(char *uri, int backlog);
-
-/**
- * Create a service instance for TCP sockets.
- *
- * @param uri		TCP socket specific URI, must start with "tcp://"
- * @param backlog	size of the backlog queue, as passed to listen()
- * @return			stream_service instance, NULL on failure
- */
-stream_service_t *stream_service_create_tcp(char *uri, int backlog);
-
 #endif /** STREAM_SERVICE_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_service_tcp.c b/src/libstrongswan/networking/streams/stream_service_tcp.c
new file mode 100644
index 0000000..4082834
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_tcp.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+#include <networking/streams/stream_tcp.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/**
+ * See header
+ */
+stream_service_t *stream_service_create_tcp(char *uri, int backlog)
+{
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+		struct sockaddr sa;
+	} addr;
+	int fd, len, on = 1;
+
+	len = stream_parse_uri_tcp(uri, &addr.sa);
+	if (len == -1)
+	{
+		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
+		return NULL;
+	}
+	fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+	if (fd < 0)
+	{
+		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+		return NULL;
+	}
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) != 0)
+	{
+		DBG1(DBG_NET, "SO_REUSADDR on '%s' failed: %s", uri, strerror(errno));
+	}
+	if (bind(fd, &addr.sa, len) < 0)
+	{
+		DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+	if (listen(fd, backlog) < 0)
+	{
+		DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+	return stream_service_create_from_fd(fd);
+}
diff --git a/src/libstrongswan/networking/streams/stream_service_tcp.h b/src/libstrongswan/networking/streams/stream_service_tcp.h
new file mode 100644
index 0000000..f63f007
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_tcp.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup stream_service_tcp stream_service_tcp
+ * @{ @ingroup stream
+ */
+
+#ifndef STREAM_SERVICE_TCP_H_
+#define STREAM_SERVICE_TCP_H_
+
+/**
+ * Create a service instance for TCP sockets.
+ *
+ * @param uri		TCP socket specific URI, must start with "tcp://"
+ * @param backlog	size of the backlog queue, as passed to listen()
+ * @return			stream_service instance, NULL on failure
+ */
+stream_service_t *stream_service_create_tcp(char *uri, int backlog);
+
+#endif /** STREAM_SERVICE_TCP_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_service_unix.c b/src/libstrongswan/networking/streams/stream_service_unix.c
new file mode 100644
index 0000000..1ed27c4
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_unix.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+#include <networking/streams/stream_unix.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+/**
+ * See header
+ */
+stream_service_t *stream_service_create_unix(char *uri, int backlog)
+{
+	struct sockaddr_un addr;
+	mode_t old;
+	int fd, len;
+
+	len = stream_parse_uri_unix(uri, &addr);
+	if (len == -1)
+	{
+		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
+		return NULL;
+	}
+	if (!lib->caps->check(lib->caps, CAP_CHOWN))
+	{	/* required to chown(2) service socket */
+		DBG1(DBG_NET, "socket '%s' requires CAP_CHOWN capability", uri);
+		return NULL;
+	}
+	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (fd == -1)
+	{
+		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+		return NULL;
+	}
+	unlink(addr.sun_path);
+
+	old = umask(S_IRWXO);
+	if (bind(fd, (struct sockaddr*)&addr, len) < 0)
+	{
+		DBG1(DBG_NET, "binding socket '%s' failed: %s", uri, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+	umask(old);
+	if (chown(addr.sun_path, lib->caps->get_uid(lib->caps),
+			  lib->caps->get_gid(lib->caps)) != 0)
+	{
+		DBG1(DBG_NET, "changing socket permissions for '%s' failed: %s",
+			 uri, strerror(errno));
+	}
+	if (listen(fd, backlog) < 0)
+	{
+		DBG1(DBG_NET, "listen on socket '%s' failed: %s", uri, strerror(errno));
+		unlink(addr.sun_path);
+		close(fd);
+		return NULL;
+	}
+	return stream_service_create_from_fd(fd);
+}
diff --git a/src/libstrongswan/networking/streams/stream_service_unix.h b/src/libstrongswan/networking/streams/stream_service_unix.h
new file mode 100644
index 0000000..14c09cb
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_service_unix.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup stream_service_unix stream_service_unix
+ * @{ @ingroup stream
+ */
+
+#ifndef STREAM_SERVICE_UNIX_H_
+#define STREAM_SERVICE_UNIX_H_
+
+/**
+ * Create a service instance for UNIX sockets.
+ *
+ * @param uri		UNIX socket specific URI, must start with "unix://"
+ * @param backlog	size of the backlog queue, as passed to listen()
+ * @return			stream_service instance, NULL on failure
+ */
+stream_service_t *stream_service_create_unix(char *uri, int backlog);
+
+/**
+ * Create a service instance for TCP sockets.
+ *
+ * @param uri		TCP socket specific URI, must start with "tcp://"
+ * @param backlog	size of the backlog queue, as passed to listen()
+ * @return			stream_service instance, NULL on failure
+ */
+stream_service_t *stream_service_create_tcp(char *uri, int backlog);
+
+#endif /** STREAM_SERVICE_UNIX_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_tcp.c b/src/libstrongswan/networking/streams/stream_tcp.c
new file mode 100644
index 0000000..5459145
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_tcp.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "stream_tcp.h"
+
+/**
+ * See header.
+ */
+int stream_parse_uri_tcp(char *uri, struct sockaddr *addr)
+{
+	char *pos, buf[128];
+	host_t *host;
+	u_long port;
+	int len;
+
+	if (!strpfx(uri, "tcp://"))
+	{
+		return -1;
+	}
+	uri += strlen("tcp://");
+	pos = strrchr(uri, ':');
+	if (!pos)
+	{
+		return -1;
+	}
+	if (*uri == '[' && pos > uri && *(pos - 1) == ']')
+	{
+		/* IPv6 URI */
+		snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri - 2), uri + 1);
+	}
+	else
+	{
+		snprintf(buf, sizeof(buf), "%.*s", (int)(pos - uri), uri);
+	}
+	port = strtoul(pos + 1, &pos, 10);
+	if (port == ULONG_MAX || *pos || port > 65535)
+	{
+		return -1;
+	}
+	host = host_create_from_dns(buf, AF_UNSPEC, port);
+	if (!host)
+	{
+		return -1;
+	}
+	len = *host->get_sockaddr_len(host);
+	memcpy(addr, host->get_sockaddr(host), len);
+	host->destroy(host);
+	return len;
+}
+
+/**
+ * See header
+ */
+stream_t *stream_create_tcp(char *uri)
+{
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+		struct sockaddr sa;
+	} addr;
+	int fd, len;
+
+	len = stream_parse_uri_tcp(uri, &addr.sa);
+	if (len == -1)
+	{
+		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
+		return NULL;
+	}
+	fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
+	if (fd < 0)
+	{
+		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+		return NULL;
+	}
+	if (connect(fd, &addr.sa, len))
+	{
+		DBG1(DBG_NET, "connecting to '%s' failed: %s", uri, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+	return stream_create_from_fd(fd);
+}
diff --git a/src/libstrongswan/networking/streams/stream_tcp.h b/src/libstrongswan/networking/streams/stream_tcp.h
new file mode 100644
index 0000000..5bf6c82
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_tcp.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup stream_tcp stream_tcp
+ * @{ @ingroup streams
+ */
+
+#ifndef STREAM_TCP_H_
+#define STREAM_TCP_H_
+
+#include <library.h>
+
+/**
+ * Create a stream for TCP sockets.
+ *
+ * TCP URIs start with tcp://, followed by a hostname (FQDN or IP), followed
+ * by a colon separated port. A full TCP uri looks something like:
+ *
+ *   tcp://srv.example.com:5555
+ *   tcp://0.0.0.0:1234
+ *   tcp://[fec2::1]:7654
+ *
+ * There is no default port, so a colon after tcp:// is mandatory.
+ *
+ * @param uri		TCP socket specific URI, must start with "tcp://"
+ * @return			stream instance, NULL on failure
+ */
+stream_t *stream_create_tcp(char *uri);
+
+/**
+ * Helper function to parse a tcp:// URI to a sockaddr
+ *
+ * @param uri		URI
+ * @param addr		sockaddr, large enough for URI
+ * @return			length of sockaddr, -1 on error
+ */
+int stream_parse_uri_tcp(char *uri, struct sockaddr *addr);
+
+#endif /** STREAM_TCP_H_ @}*/
diff --git a/src/libstrongswan/networking/streams/stream_unix.c b/src/libstrongswan/networking/streams/stream_unix.c
new file mode 100644
index 0000000..13e56bc
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_unix.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "stream_unix.h"
+
+/**
+ * See header
+ */
+int stream_parse_uri_unix(char *uri, struct sockaddr_un *addr)
+{
+	if (!strpfx(uri, "unix://"))
+	{
+		return -1;
+	}
+	uri += strlen("unix://");
+
+	memset(addr, 0, sizeof(*addr));
+	addr->sun_family = AF_UNIX;
+	strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
+	addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
+
+	return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
+}
+
+/**
+ * See header
+ */
+stream_t *stream_create_unix(char *uri)
+{
+	struct sockaddr_un addr;
+	int len, fd;
+
+	len = stream_parse_uri_unix(uri, &addr);
+	if (len == -1)
+	{
+		DBG1(DBG_NET, "invalid stream URI: '%s'", uri);
+		return NULL;
+	}
+	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (fd < 0)
+	{
+		DBG1(DBG_NET, "opening socket '%s' failed: %s", uri, strerror(errno));
+		return NULL;
+	}
+	if (connect(fd, (struct sockaddr*)&addr, len) < 0)
+	{
+		DBG1(DBG_NET, "connecting to '%s' failed: %s", uri, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+	return stream_create_from_fd(fd);
+}
diff --git a/src/libstrongswan/networking/streams/stream_unix.h b/src/libstrongswan/networking/streams/stream_unix.h
new file mode 100644
index 0000000..5204251
--- /dev/null
+++ b/src/libstrongswan/networking/streams/stream_unix.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup stream_unix stream_unix
+ * @{ @ingroup streams
+ */
+
+#ifndef STREAM_UNIX_H_
+#define STREAM_UNIX_H_
+
+#include <sys/un.h>
+
+/**
+ * Create a stream for UNIX sockets.
+ *
+ * UNIX URIs start with unix://, followed by the socket path. For absolute
+ * paths, an URI looks something like:
+ *
+ *   unix:///path/to/socket
+ *
+ * @param uri		UNIX socket specific URI, must start with "unix://"
+ * @return			stream instance, NULL on failure
+ */
+stream_t *stream_create_unix(char *uri);
+
+/**
+ * Helper function to parse a unix:// URI to a sockaddr
+ *
+ * @param uri		URI
+ * @param addr		sockaddr
+ * @return			length of sockaddr, -1 on error
+ */
+int stream_parse_uri_unix(char *uri, struct sockaddr_un *addr);
+
+#endif /** STREAM_UNIX_H_ @}*/
diff --git a/src/libstrongswan/networking/tun_device.c b/src/libstrongswan/networking/tun_device.c
index ecefdc2..ff2c4a3 100644
--- a/src/libstrongswan/networking/tun_device.c
+++ b/src/libstrongswan/networking/tun_device.c
@@ -16,24 +16,12 @@
  * for more details.
  */
 
-#include <errno.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <net/if.h>
-
-#if !defined(__APPLE__) && !defined(__linux__) && !defined(HAVE_NET_IF_TUN_H)
-
 #include "tun_device.h"
 
 #include <utils/debug.h>
+#include <threading/thread.h>
 
-#warning TUN devices are not supported!
+#if !defined(__APPLE__) && !defined(__linux__) && !defined(HAVE_NET_IF_TUN_H)
 
 tun_device_t *tun_device_create(const char *name_tmpl)
 {
@@ -43,6 +31,17 @@ tun_device_t *tun_device_create(const char *name_tmpl)
 
 #else /* TUN devices supported */
 
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <net/if.h>
+
 #ifdef __APPLE__
 #include <net/if_utun.h>
 #include <netinet/in_var.h>
@@ -50,15 +49,14 @@ tun_device_t *tun_device_create(const char *name_tmpl)
 #elif defined(__linux__)
 #include <linux/types.h>
 #include <linux/if_tun.h>
+#elif __FreeBSD__ >= 10
+#include <net/if_tun.h>
+#include <net/if_var.h>
+#include <netinet/in_var.h>
 #else
 #include <net/if_tun.h>
 #endif
 
-#include "tun_device.h"
-
-#include <utils/debug.h>
-#include <threading/thread.h>
-
 #define TUN_DEFAULT_MTU 1500
 
 typedef struct private_tun_device_t private_tun_device_t;
@@ -101,8 +99,79 @@ struct private_tun_device_t {
 	u_int8_t netmask;
 };
 
-METHOD(tun_device_t, set_address, bool,
-	private_tun_device_t *this, host_t *addr, u_int8_t netmask)
+/**
+ * FreeBSD 10 deprecated the SIOCSIFADDR etc. commands.
+ */
+#if __FreeBSD__ >= 10
+
+static bool set_address_and_mask(struct in_aliasreq *ifra, host_t *addr,
+								 u_int8_t netmask)
+{
+	host_t *mask;
+
+	memcpy(&ifra->ifra_addr, addr->get_sockaddr(addr),
+		   *addr->get_sockaddr_len(addr));
+	/* set the same address as destination address */
+	memcpy(&ifra->ifra_dstaddr, addr->get_sockaddr(addr),
+		   *addr->get_sockaddr_len(addr));
+
+	mask = host_create_netmask(addr->get_family(addr), netmask);
+	if (!mask)
+	{
+		DBG1(DBG_LIB, "invalid netmask: %d", netmask);
+		return FALSE;
+	}
+	memcpy(&ifra->ifra_mask, mask->get_sockaddr(mask),
+		   *mask->get_sockaddr_len(mask));
+	mask->destroy(mask);
+	return TRUE;
+}
+
+/**
+ * Set the address using the more flexible SIOCAIFADDR/SIOCDIFADDR commands
+ * on FreeBSD 10 an newer.
+ */
+static bool set_address_impl(private_tun_device_t *this, host_t *addr,
+							 u_int8_t netmask)
+{
+	struct in_aliasreq ifra;
+
+	memset(&ifra, 0, sizeof(ifra));
+	strncpy(ifra.ifra_name, this->if_name, IFNAMSIZ);
+
+	if (this->address)
+	{	/* remove the existing address first */
+		if (!set_address_and_mask(&ifra, this->address, this->netmask))
+		{
+			return FALSE;
+		}
+		if (ioctl(this->sock, SIOCDIFADDR, &ifra) < 0)
+		{
+			DBG1(DBG_LIB, "failed to remove existing address on %s: %s",
+				 this->if_name, strerror(errno));
+			return FALSE;
+		}
+	}
+	if (!set_address_and_mask(&ifra, addr, netmask))
+	{
+		return FALSE;
+	}
+	if (ioctl(this->sock, SIOCAIFADDR, &ifra) < 0)
+	{
+		DBG1(DBG_LIB, "failed to add address on %s: %s",
+			 this->if_name, strerror(errno));
+		return FALSE;
+	}
+	return TRUE;
+}
+
+#else /* __FreeBSD__ */
+
+/**
+ * Set the address using the classic SIOCSIFADDR etc. commands on other systems.
+ */
+static bool set_address_impl(private_tun_device_t *this, host_t *addr,
+							 u_int8_t netmask)
 {
 	struct ifreq ifr;
 	host_t *mask;
@@ -143,6 +212,19 @@ METHOD(tun_device_t, set_address, bool,
 			 this->if_name, strerror(errno));
 		return FALSE;
 	}
+	return TRUE;
+}
+
+#endif /* __FreeBSD__ */
+
+METHOD(tun_device_t, set_address, bool,
+	private_tun_device_t *this, host_t *addr, u_int8_t netmask)
+{
+	if (!set_address_impl(this, addr, netmask))
+	{
+		return FALSE;
+	}
+	DESTROY_IF(this->address);
 	this->address = addr->clone(addr);
 	this->netmask = netmask;
 	return TRUE;
diff --git a/src/libstrongswan/plugins/acert/Makefile.am b/src/libstrongswan/plugins/acert/Makefile.am
index ba16f41..558034e 100644
--- a/src/libstrongswan/plugins/acert/Makefile.am
+++ b/src/libstrongswan/plugins/acert/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-acert.la
diff --git a/src/libstrongswan/plugins/acert/Makefile.in b/src/libstrongswan/plugins/acert/Makefile.in
index 3dd650d..eb148e7 100644
--- a/src/libstrongswan/plugins/acert/Makefile.in
+++ b/src/libstrongswan/plugins/acert/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-acert.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-acert.la
diff --git a/src/libstrongswan/plugins/aes/Makefile.am b/src/libstrongswan/plugins/aes/Makefile.am
index 8c5505b..cfdcf49 100644
--- a/src/libstrongswan/plugins/aes/Makefile.am
+++ b/src/libstrongswan/plugins/aes/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-aes.la
diff --git a/src/libstrongswan/plugins/aes/Makefile.in b/src/libstrongswan/plugins/aes/Makefile.in
index f9c0750..dfe4117 100644
--- a/src/libstrongswan/plugins/aes/Makefile.in
+++ b/src/libstrongswan/plugins/aes/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-aes.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-aes.la
diff --git a/src/libstrongswan/plugins/aes/aes_crypter.c b/src/libstrongswan/plugins/aes/aes_crypter.c
index 6b3d03c..f9775c8 100644
--- a/src/libstrongswan/plugins/aes/aes_crypter.c
+++ b/src/libstrongswan/plugins/aes/aes_crypter.c
@@ -49,90 +49,29 @@ struct private_aes_crypter_t {
 	/**
 	 * Number of words in the key input block.
 	 */
-	u_int32_t    aes_Nkey;
+	u_int32_t aes_Nkey;
 
 	/**
 	 * The number of cipher rounds.
 	 */
-	u_int32_t    aes_Nrnd;
+	u_int32_t aes_Nrnd;
 
 	/**
 	* The encryption key schedule.
 	*/
-	u_int32_t    aes_e_key[AES_KS_LENGTH];
+	u_int32_t aes_e_key[AES_KS_LENGTH];
 
 	/**
 	* The decryption key schedule.
 	*/
-	u_int32_t    aes_d_key[AES_KS_LENGTH];
+	u_int32_t aes_d_key[AES_KS_LENGTH];
 
 	/**
 	* Key size of this AES cypher object.
 	*/
-	u_int32_t    key_size;
+	u_int32_t key_size;
 };
 
-
-/* ugly macro stuff */
-
-/* 1.  Define UNROLL for full loop unrolling in encryption and decryption.
- * 2.  Define PARTIAL_UNROLL to unroll two loops in encryption and decryption.
- * 3.  Define FIXED_TABLES for compiled rather than dynamic tables.
- * 4.  Define FF_TABLES to use tables for field multiplies and inverses.
- *     Do not enable this without understanding stack space requirements.
- * 5.  Define ARRAYS to use arrays to hold the local state block. If this
- *     is not defined, individually declared 32-bit words are used.
- * 6.  Define FAST_VARIABLE if a high speed variable block implementation
- *     is needed (essentially three separate fixed block size code sequences)
- * 7.  Define either ONE_TABLE or FOUR_TABLES for a fast table driven
- *     version using 1 table (2 kbytes of table space) or 4 tables (8
- *     kbytes of table space) for higher speed.
- * 8.  Define either ONE_LR_TABLE or FOUR_LR_TABLES for a further speed
- *     increase by using tables for the last rounds but with more table
- *     space (2 or 8 kbytes extra).
- * 9.  If neither ONE_TABLE nor FOUR_TABLES is defined, a compact but
- *     slower version is provided.
- * 10. If fast decryption key scheduling is needed define ONE_IM_TABLE
- *     or FOUR_IM_TABLES for higher speed (2 or 8 kbytes extra).
- */
-
-#define UNROLL
-//#define PARTIAL_UNROLL
-
-#define FIXED_TABLES
-//#define FF_TABLES
-//#define ARRAYS
-#define FAST_VARIABLE
-
-//#define ONE_TABLE
-#define FOUR_TABLES
-
-//#define ONE_LR_TABLE
-#define FOUR_LR_TABLES
-
-//#define ONE_IM_TABLE
-#define FOUR_IM_TABLES
-
-#if defined(UNROLL) && defined (PARTIAL_UNROLL)
-#error both UNROLL and PARTIAL_UNROLL are defined
-#endif
-
-#if defined(ONE_TABLE) && defined (FOUR_TABLES)
-#error both ONE_TABLE and FOUR_TABLES are defined
-#endif
-
-#if defined(ONE_LR_TABLE) && defined (FOUR_LR_TABLES)
-#error both ONE_LR_TABLE and FOUR_LR_TABLES are defined
-#endif
-
-#if defined(ONE_IM_TABLE) && defined (FOUR_IM_TABLES)
-#error both ONE_IM_TABLE and FOUR_IM_TABLES are defined
-#endif
-
-#if defined(AES_BLOCK_SIZE) && AES_BLOCK_SIZE != 16 && AES_BLOCK_SIZE != 24 && AES_BLOCK_SIZE != 32
-#error an illegal block size has been specified
-#endif
-
 /**
  * Rotates bytes within words by n positions, moving bytes
  * to higher index positions with wrap around into low positions.
@@ -179,31 +118,6 @@ struct private_aes_crypter_t {
 #define const_word_out(x,v)   ((const unsigned char *)(x))[0]=(v),((const unsigned char *)(x))[1]=((v)>>8),((const unsigned char *)(x))[2]=((v)>>16),((const unsigned char *)(x))[3]=((v)>>24)
 #endif
 
-// Disable at least some poor combinations of options
-
-#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
-#define FIXED_TABLES
-#undef  UNROLL
-#undef  ONE_LR_TABLE
-#undef  FOUR_LR_TABLES
-#undef  ONE_IM_TABLE
-#undef  FOUR_IM_TABLES
-#elif !defined(FOUR_TABLES)
-#ifdef  FOUR_LR_TABLES
-#undef  FOUR_LR_TABLES
-#define ONE_LR_TABLE
-#endif
-#ifdef  FOUR_IM_TABLES
-#undef  FOUR_IM_TABLES
-#define ONE_IM_TABLE
-#endif
-#elif !defined(AES_BLOCK_SIZE)
-#if defined(UNROLL)
-#define PARTIAL_UNROLL
-#undef UNROLL
-#endif
-#endif
-
 // the finite field modular polynomial and elements
 
 #define ff_poly 0x011b
@@ -228,84 +142,6 @@ struct private_aes_crypter_t {
 
 #define fwd_mcol(x) (f2 = FFmulX(x), f2 ^ upr(x ^ f2,3) ^ upr(x,2) ^ upr(x,1))
 
-#if defined(FIXED_TABLES)
-
-// the S-Box table
-
-static const unsigned char s_box[256] =
-{
-    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
-    0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
-    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
-    0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
-    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
-    0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
-    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
-    0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
-    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
-    0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
-    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
-    0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
-    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
-    0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
-    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
-    0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
-    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
-    0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
-    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
-    0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
-    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
-    0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
-    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
-    0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
-    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
-    0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
-    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
-    0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
-    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
-    0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
-    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
-    0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
-};
-
-// the inverse S-Box table
-
-static const unsigned char inv_s_box[256] =
-{
-    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
-    0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
-    0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
-    0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
-    0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
-    0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
-    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
-    0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
-    0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
-    0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
-    0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
-    0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
-    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
-    0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
-    0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
-    0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
-    0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
-    0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
-    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
-    0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
-    0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
-    0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
-    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
-    0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
-    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
-    0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
-    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
-    0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
-    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
-    0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
-    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
-    0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
-};
-
 #define w0(p)          0x000000##p
 
 // Number of elements required in this table for different
@@ -343,8 +179,6 @@ static const u_int32_t rcon_tab[29] =
 #define w2(p)        0x00##p##0000
 #define w3(p)        0x##p##000000
 
-#if defined(FIXED_TABLES) && (defined(ONE_TABLE) || defined(FOUR_TABLES))
-
 //  data for forward tables (other than last round)
 
 #define f_table \
@@ -486,10 +320,6 @@ static const u_int32_t rcon_tab[29] =
 #undef  r
 #define r   r0
 
-#if defined(ONE_TABLE)
-static const u_int32_t ft_tab[256] =
-    {   f_table };
-#elif defined(FOUR_TABLES)
 static const u_int32_t ft_tab[4][256] =
 {   {   f_table },
 #undef  r
@@ -502,14 +332,9 @@ static const u_int32_t ft_tab[4][256] =
 #define r   r3
     {   f_table }
 };
-#endif
 
 #undef  r
 #define r   r0
-#if defined(ONE_TABLE)
-static const u_int32_t it_tab[256] =
-    {   i_table };
-#elif defined(FOUR_TABLES)
 static const u_int32_t it_tab[4][256] =
 {   {   i_table },
 #undef  r
@@ -522,13 +347,6 @@ static const u_int32_t it_tab[4][256] =
 #define r   r3
     {   i_table }
 };
-#endif
-
-#endif
-
-#if defined(FIXED_TABLES) && (defined(ONE_LR_TABLE) || defined(FOUR_LR_TABLES))
-
-//  data for inverse tables (last round)
 
 #define li_table    \
     w(52), w(09), w(6a), w(d5), w(30), w(36), w(a5), w(38),\
@@ -568,10 +386,6 @@ static const u_int32_t it_tab[4][256] =
 
 #undef  r
 #define r(p,q,r,s)  w0(q)
-#if defined(ONE_LR_TABLE)
-static const u_int32_t fl_tab[256] =
-    {   f_table     };
-#elif defined(FOUR_LR_TABLES)
 static const u_int32_t fl_tab[4][256] =
 {   {   f_table    },
 #undef  r
@@ -584,14 +398,9 @@ static const u_int32_t fl_tab[4][256] =
 #define r(p,q,r,s)   w3(q)
     {   f_table    }
 };
-#endif
 
 #undef  w
 #define w   w0
-#if defined(ONE_LR_TABLE)
-static const u_int32_t il_tab[256] =
-    {   li_table    };
-#elif defined(FOUR_LR_TABLES)
 static const u_int32_t il_tab[4][256] =
 {   {   li_table    },
 #undef  w
@@ -604,11 +413,6 @@ static const u_int32_t il_tab[4][256] =
 #define w   w3
     {   li_table    }
 };
-#endif
-
-#endif
-
-#if defined(FIXED_TABLES) && (defined(ONE_IM_TABLE) || defined(FOUR_IM_TABLES))
 
 #define m_table \
     r(00,00,00,00), r(0b,0d,09,0e), r(16,1a,12,1c), r(1d,17,1b,12),\
@@ -679,10 +483,6 @@ static const u_int32_t il_tab[4][256] =
 #undef r
 #define r   r0
 
-#if defined(ONE_IM_TABLE)
-static const u_int32_t im_tab[256] =
-    {   m_table };
-#elif defined(FOUR_IM_TABLES)
 static const u_int32_t im_tab[4][256] =
 {   {   m_table },
 #undef  r
@@ -695,212 +495,6 @@ static const u_int32_t im_tab[4][256] =
 #define r   r3
     {   m_table }
 };
-#endif
-
-#endif
-
-#else
-
-static int tab_gen = 0;
-
-static unsigned char  s_box[256];            // the S box
-static unsigned char  inv_s_box[256];        // the inverse S box
-static u_int32_t  rcon_tab[AES_RC_LENGTH];   // table of round constants
-
-#if defined(ONE_TABLE)
-static u_int32_t  ft_tab[256];
-static u_int32_t  it_tab[256];
-#elif defined(FOUR_TABLES)
-static u_int32_t  ft_tab[4][256];
-static u_int32_t  it_tab[4][256];
-#endif
-
-#if defined(ONE_LR_TABLE)
-static u_int32_t  fl_tab[256];
-static u_int32_t  il_tab[256];
-#elif defined(FOUR_LR_TABLES)
-static u_int32_t  fl_tab[4][256];
-static u_int32_t  il_tab[4][256];
-#endif
-
-#if defined(ONE_IM_TABLE)
-static u_int32_t  im_tab[256];
-#elif defined(FOUR_IM_TABLES)
-static u_int32_t  im_tab[4][256];
-#endif
-
-// Generate the tables for the dynamic table option
-
-#if !defined(FF_TABLES)
-
-// It will generally be sensible to use tables to compute finite
-// field multiplies and inverses but where memory is scarse this
-// code might sometimes be better.
-
-// return 2 ^ (n - 1) where n is the bit number of the highest bit
-// set in x with x in the range 1 < x < 0x00000200.   This form is
-// used so that locals within FFinv can be bytes rather than words
-
-static unsigned char hibit(const u_int32_t x)
-{   unsigned char r = (unsigned char)((x >> 1) | (x >> 2));
-
-    r |= (r >> 2);
-    r |= (r >> 4);
-    return (r + 1) >> 1;
-}
-
-// return the inverse of the finite field element x
-
-static unsigned char FFinv(const unsigned char x)
-{   unsigned char    p1 = x, p2 = 0x1b, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
-
-    if(x < 2) return x;
-
-    for(;;)
-    {
-        if(!n1) return v1;
-
-        while(n2 >= n1)
-        {
-            n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
-        }
-
-        if(!n2) return v2;
-
-        while(n1 >= n2)
-        {
-            n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
-        }
-    }
-}
-
-// define the finite field multiplies required for Rijndael
-
-#define FFmul02(x)  ((((x) & 0x7f) << 1) ^ ((x) & 0x80 ? 0x1b : 0))
-#define FFmul03(x)  ((x) ^ FFmul02(x))
-#define FFmul09(x)  ((x) ^ FFmul02(FFmul02(FFmul02(x))))
-#define FFmul0b(x)  ((x) ^ FFmul02((x) ^ FFmul02(FFmul02(x))))
-#define FFmul0d(x)  ((x) ^ FFmul02(FFmul02((x) ^ FFmul02(x))))
-#define FFmul0e(x)  FFmul02((x) ^ FFmul02((x) ^ FFmul02(x)))
-
-#else
-
-#define FFinv(x)    ((x) ? pow[255 - log[x]]: 0)
-
-#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0)
-#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0)
-#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0)
-#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0)
-#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0)
-#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0)
-
-#endif
-
-// The forward and inverse affine transformations used in the S-box
-
-#define fwd_affine(x) \
-    (w = (u_int32_t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(unsigned char)(w^(w>>8)))
-
-#define inv_affine(x) \
-    (w = (u_int32_t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(unsigned char)(w^(w>>8)))
-
-static void gen_tabs(void)
-{   u_int32_t  i, w;
-
-#if defined(FF_TABLES)
-
-    unsigned char  pow[512], log[256];
-
-    // log and power tables for GF(2^8) finite field with
-    // 0x011b as modular polynomial - the simplest primitive
-    // root is 0x03, used here to generate the tables
-
-    i = 0; w = 1;
-    do
-    {
-        pow[i] = (unsigned char)w;
-        pow[i + 255] = (unsigned char)w;
-        log[w] = (unsigned char)i++;
-        w ^=  (w << 1) ^ (w & ff_hi ? ff_poly : 0);
-    }
-    while (w != 1);
-
-#endif
-
-    for(i = 0, w = 1; i < AES_RC_LENGTH; ++i)
-    {
-        rcon_tab[i] = bytes2word(w, 0, 0, 0);
-        w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
-    }
-
-    for(i = 0; i < 256; ++i)
-    {   unsigned char    b;
-
-        s_box[i] = b = fwd_affine(FFinv((unsigned char)i));
-
-        w = bytes2word(b, 0, 0, 0);
-#if defined(ONE_LR_TABLE)
-        fl_tab[i] = w;
-#elif defined(FOUR_LR_TABLES)
-        fl_tab[0][i] = w;
-        fl_tab[1][i] = upr(w,1);
-        fl_tab[2][i] = upr(w,2);
-        fl_tab[3][i] = upr(w,3);
-#endif
-        w = bytes2word(FFmul02(b), b, b, FFmul03(b));
-#if defined(ONE_TABLE)
-        ft_tab[i] = w;
-#elif defined(FOUR_TABLES)
-        ft_tab[0][i] = w;
-        ft_tab[1][i] = upr(w,1);
-        ft_tab[2][i] = upr(w,2);
-        ft_tab[3][i] = upr(w,3);
-#endif
-        inv_s_box[i] = b = FFinv(inv_affine((unsigned char)i));
-
-        w = bytes2word(b, 0, 0, 0);
-#if defined(ONE_LR_TABLE)
-        il_tab[i] = w;
-#elif defined(FOUR_LR_TABLES)
-        il_tab[0][i] = w;
-        il_tab[1][i] = upr(w,1);
-        il_tab[2][i] = upr(w,2);
-        il_tab[3][i] = upr(w,3);
-#endif
-        w = bytes2word(FFmul0e(b), FFmul09(b), FFmul0d(b), FFmul0b(b));
-#if defined(ONE_TABLE)
-        it_tab[i] = w;
-#elif defined(FOUR_TABLES)
-        it_tab[0][i] = w;
-        it_tab[1][i] = upr(w,1);
-        it_tab[2][i] = upr(w,2);
-        it_tab[3][i] = upr(w,3);
-#endif
-#if defined(ONE_IM_TABLE)
-        im_tab[b] = w;
-#elif defined(FOUR_IM_TABLES)
-        im_tab[0][b] = w;
-        im_tab[1][b] = upr(w,1);
-        im_tab[2][b] = upr(w,2);
-        im_tab[3][b] = upr(w,3);
-#endif
-
-    }
-}
-
-#endif
-
-#define no_table(x,box,vf,rf,c) bytes2word( \
-    box[bval(vf(x,0,c),rf(0,c))], \
-    box[bval(vf(x,1,c),rf(1,c))], \
-    box[bval(vf(x,2,c),rf(2,c))], \
-    box[bval(vf(x,3,c),rf(3,c))])
-
-#define one_table(x,op,tab,vf,rf,c) \
- (     tab[bval(vf(x,0,c),rf(0,c))] \
-  ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \
-  ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \
-  ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))
 
 #define four_tables(x,tab,vf,rf,c) \
  (  tab[0][bval(vf(x,0,c),rf(0,c))] \
@@ -912,23 +506,8 @@ static void gen_tabs(void)
 #define rf1(r,c)    (r)
 #define rf2(r,c)    ((r-c)&3)
 
-#if defined(FOUR_LR_TABLES)
 #define ls_box(x,c)     four_tables(x,fl_tab,vf1,rf2,c)
-#elif defined(ONE_LR_TABLE)
-#define ls_box(x,c)     one_table(x,upr,fl_tab,vf1,rf2,c)
-#else
-#define ls_box(x,c)     no_table(x,s_box,vf1,rf2,c)
-#endif
-
-#if defined(FOUR_IM_TABLES)
 #define inv_mcol(x)     four_tables(x,im_tab,vf1,rf1,0)
-#elif defined(ONE_IM_TABLE)
-#define inv_mcol(x)     one_table(x,upr,im_tab,vf1,rf1,0)
-#else
-#define inv_mcol(x) \
-    (f9 = (x),f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \
-    f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1))
-#endif
 
 #define nc   (AES_BLOCK_SIZE/4)
 
@@ -954,23 +533,7 @@ static void gen_tabs(void)
 #define mix(d,s)    mx(d,s); mx(d,s); mx(d,s); mx(d,s); \
                     mx(d,s); mx(d,s); mx(d,s); mx(d,s)
 #else
-
-#define cpy(d,s) \
-switch(nc) \
-{   case 8: cp(d,s); cp(d,s); \
-    case 6: cp(d,s); cp(d,s); \
-    case 4: cp(d,s); cp(d,s); \
-            cp(d,s); cp(d,s); \
-}
-
-#define mix(d,s) \
-switch(nc) \
-{   case 8: mx(d,s); mx(d,s); \
-    case 6: mx(d,s); mx(d,s); \
-    case 4: mx(d,s); mx(d,s); \
-            mx(d,s); mx(d,s); \
-}
-
+#error bad AES_BLOCK_SIZE
 #endif
 
 // y = output word, x = input word, r = row, c = column
@@ -1072,27 +635,10 @@ switch(nc) \
 #define si(y,x,k,c) s(y,c) = const_word_in(x + 4 * c) ^ k[c]
 #define so(y,x,c)   word_out(y + 4 * c, s(x,c))
 
-#if defined(FOUR_TABLES)
 #define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c)
 #define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c)
-#elif defined(ONE_TABLE)
-#define fwd_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c)
-#define inv_rnd(y,x,k,c)    s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c)
-#else
-#define fwd_rnd(y,x,k,c)    s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c]
-#define inv_rnd(y,x,k,c)    s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c])
-#endif
-
-#if defined(FOUR_LR_TABLES)
 #define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c)
 #define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c)
-#elif defined(ONE_LR_TABLE)
-#define fwd_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c)
-#define inv_lrnd(y,x,k,c)   s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c)
-#else
-#define fwd_lrnd(y,x,k,c)   s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c]
-#define inv_lrnd(y,x,k,c)   s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]
-#endif
 
 #if AES_BLOCK_SIZE == 16
 
@@ -1160,175 +706,83 @@ switch(nc) \
 #define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \
                         rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7)
 #else
-
-#define state_in(y,x,k) \
-switch(nc) \
-{   case 8: si(y,x,k,7); si(y,x,k,6); \
-    case 6: si(y,x,k,5); si(y,x,k,4); \
-    case 4: si(y,x,k,3); si(y,x,k,2); \
-            si(y,x,k,1); si(y,x,k,0); \
-}
-
-#define state_out(y,x) \
-switch(nc) \
-{   case 8: so(y,x,7); so(y,x,6); \
-    case 6: so(y,x,5); so(y,x,4); \
-    case 4: so(y,x,3); so(y,x,2); \
-            so(y,x,1); so(y,x,0); \
-}
-
-#if defined(FAST_VARIABLE)
-
-#define round(rm,y,x,k) \
-switch(nc) \
-{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
-            rm(y,x,k,5); rm(y,x,k,4); \
-            rm(y,x,k,3); rm(y,x,k,2); \
-            rm(y,x,k,1); rm(y,x,k,0); \
-            break; \
-    case 6: rm(y,x,k,5); rm(y,x,k,4); \
-            rm(y,x,k,3); rm(y,x,k,2); \
-            rm(y,x,k,1); rm(y,x,k,0); \
-            break; \
-    case 4: rm(y,x,k,3); rm(y,x,k,2); \
-            rm(y,x,k,1); rm(y,x,k,0); \
-            break; \
-}
-#else
-
-#define round(rm,y,x,k) \
-switch(nc) \
-{   case 8: rm(y,x,k,7); rm(y,x,k,6); \
-    case 6: rm(y,x,k,5); rm(y,x,k,4); \
-    case 4: rm(y,x,k,3); rm(y,x,k,2); \
-            rm(y,x,k,1); rm(y,x,k,0); \
-}
-
+#error invalid AES_BLOCK_SIZE
 #endif
 
 #endif
-#endif
 
 /**
  * Encrypt a single block of data.
  */
-static void encrypt_block(const private_aes_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
-{   u_int32_t        locals(b0, b1);
-    const u_int32_t  *kp = this->aes_e_key;
-
-#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
-    u_int32_t        f2;
-#endif
-
-    state_in(b0, in_blk, kp); kp += nc;
-
-#if defined(UNROLL)
-
-    switch(this->aes_Nrnd)
-    {
-    case 14:    round(fwd_rnd,  b1, b0, kp         );
-                round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
-    case 12:    round(fwd_rnd,  b1, b0, kp         );
-                round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
-    case 10:    round(fwd_rnd,  b1, b0, kp         );
-                round(fwd_rnd,  b0, b1, kp +     nc);
-                round(fwd_rnd,  b1, b0, kp + 2 * nc);
-                round(fwd_rnd,  b0, b1, kp + 3 * nc);
-                round(fwd_rnd,  b1, b0, kp + 4 * nc);
-                round(fwd_rnd,  b0, b1, kp + 5 * nc);
-                round(fwd_rnd,  b1, b0, kp + 6 * nc);
-                round(fwd_rnd,  b0, b1, kp + 7 * nc);
-                round(fwd_rnd,  b1, b0, kp + 8 * nc);
-                round(fwd_lrnd, b0, b1, kp + 9 * nc);
-    }
-
-#elif defined(PARTIAL_UNROLL)
-    {   u_int32_t    rnd;
-
-        for(rnd = 0; rnd < (this->aes_Nrnd >> 1) - 1; ++rnd)
-        {
-            round(fwd_rnd, b1, b0, kp);
-            round(fwd_rnd, b0, b1, kp + nc); kp += 2 * nc;
-        }
-
-        round(fwd_rnd,  b1, b0, kp);
-        round(fwd_lrnd, b0, b1, kp + nc);
-    }
-#else
-    {   u_int32_t    rnd;
+static void encrypt_block(const private_aes_crypter_t *this,
+						  const unsigned char in_blk[], unsigned char out_blk[])
+{
+	u_int32_t locals(b0, b1);
+	const u_int32_t *kp = this->aes_e_key;
 
-        for(rnd = 0; rnd < this->aes_Nrnd - 1; ++rnd)
-        {
-            round(fwd_rnd, b1, b0, kp);
-            l_copy(b0, b1); kp += nc;
-        }
+	state_in(b0, in_blk, kp); kp += nc;
 
-        round(fwd_lrnd, b0, b1, kp);
-    }
-#endif
+	switch(this->aes_Nrnd)
+	{
+		case 14:
+			round(fwd_rnd,  b1, b0, kp         );
+			round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+			/* fall */
+		case 12:
+			round(fwd_rnd,  b1, b0, kp         );
+			round(fwd_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+			/* fall */
+		case 10:
+			round(fwd_rnd,  b1, b0, kp         );
+			round(fwd_rnd,  b0, b1, kp +     nc);
+			round(fwd_rnd,  b1, b0, kp + 2 * nc);
+			round(fwd_rnd,  b0, b1, kp + 3 * nc);
+			round(fwd_rnd,  b1, b0, kp + 4 * nc);
+			round(fwd_rnd,  b0, b1, kp + 5 * nc);
+			round(fwd_rnd,  b1, b0, kp + 6 * nc);
+			round(fwd_rnd,  b0, b1, kp + 7 * nc);
+			round(fwd_rnd,  b1, b0, kp + 8 * nc);
+			round(fwd_lrnd, b0, b1, kp + 9 * nc);
+	}
 
-    state_out(out_blk, b0);
+	state_out(out_blk, b0);
 }
 
 /**
  * Decrypt a single block of data.
  */
-static void decrypt_block(const private_aes_crypter_t *this, const unsigned char in_blk[], unsigned char out_blk[])
-{   u_int32_t        locals(b0, b1);
-    const u_int32_t  *kp = this->aes_d_key;
-
-#if !defined(ONE_TABLE) && !defined(FOUR_TABLES)
-    u_int32_t        f2, f4, f8, f9;
-#endif
-
-    state_in(b0, in_blk, kp); kp += nc;
-
-#if defined(UNROLL)
-
-    switch(this->aes_Nrnd)
-    {
-    case 14:    round(inv_rnd,  b1, b0, kp         );
-                round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
-    case 12:    round(inv_rnd,  b1, b0, kp         );
-                round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
-    case 10:    round(inv_rnd,  b1, b0, kp         );
-                round(inv_rnd,  b0, b1, kp +     nc);
-                round(inv_rnd,  b1, b0, kp + 2 * nc);
-                round(inv_rnd,  b0, b1, kp + 3 * nc);
-                round(inv_rnd,  b1, b0, kp + 4 * nc);
-                round(inv_rnd,  b0, b1, kp + 5 * nc);
-                round(inv_rnd,  b1, b0, kp + 6 * nc);
-                round(inv_rnd,  b0, b1, kp + 7 * nc);
-                round(inv_rnd,  b1, b0, kp + 8 * nc);
-                round(inv_lrnd, b0, b1, kp + 9 * nc);
-    }
-
-#elif defined(PARTIAL_UNROLL)
-    {   u_int32_t    rnd;
-
-        for(rnd = 0; rnd < (this->aes_Nrnd >> 1) - 1; ++rnd)
-        {
-            round(inv_rnd, b1, b0, kp);
-            round(inv_rnd, b0, b1, kp + nc); kp += 2 * nc;
-        }
-
-        round(inv_rnd,  b1, b0, kp);
-        round(inv_lrnd, b0, b1, kp + nc);
-    }
-#else
-    {   u_int32_t    rnd;
+static void decrypt_block(const private_aes_crypter_t *this,
+						  const unsigned char in_blk[], unsigned char out_blk[])
+{
+	u_int32_t locals(b0, b1);
+	const u_int32_t *kp = this->aes_d_key;
 
-        for(rnd = 0; rnd < this->aes_Nrnd - 1; ++rnd)
-        {
-            round(inv_rnd, b1, b0, kp);
-            l_copy(b0, b1); kp += nc;
-        }
+	state_in(b0, in_blk, kp); kp += nc;
 
-        round(inv_lrnd, b0, b1, kp);
-    }
-#endif
+	switch(this->aes_Nrnd)
+	{
+		case 14:
+			round(inv_rnd,  b1, b0, kp         );
+			round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+			/* fall */
+		case 12:
+			round(inv_rnd,  b1, b0, kp         );
+			round(inv_rnd,  b0, b1, kp + nc    ); kp += 2 * nc;
+			/* fall */
+		case 10:
+			round(inv_rnd,  b1, b0, kp         );
+			round(inv_rnd,  b0, b1, kp +     nc);
+			round(inv_rnd,  b1, b0, kp + 2 * nc);
+			round(inv_rnd,  b0, b1, kp + 3 * nc);
+			round(inv_rnd,  b1, b0, kp + 4 * nc);
+			round(inv_rnd,  b0, b1, kp + 5 * nc);
+			round(inv_rnd,  b1, b0, kp + 6 * nc);
+			round(inv_rnd,  b0, b1, kp + 7 * nc);
+			round(inv_rnd,  b1, b0, kp + 8 * nc);
+			round(inv_lrnd, b0, b1, kp + 9 * nc);
+	}
 
-    state_out(out_blk, b0);
+	state_out(out_blk, b0);
 }
 
 METHOD(crypter_t, decrypt, bool,
@@ -1503,14 +957,7 @@ METHOD(crypter_t, set_key, bool,
 
 		for(i = 1; i < this->aes_Nrnd; ++i)
 		{
-#if defined(ONE_TABLE) || defined(FOUR_TABLES)
-#if !defined(ONE_IM_TABLE) && !defined(FOUR_IM_TABLES)
-			u_int32_t    f2, f4, f8, f9;
-#endif
 			mix(kt, kf);
-#else
-			cpy(kt, kf);
-#endif
 			kt -= 2 * nc;
 		}
 		cpy(kt, kf);
@@ -1549,10 +996,6 @@ aes_crypter_t *aes_crypter_create(encryption_algorithm_t algo, size_t key_size)
 			return NULL;
 	}
 
-	#if !defined(FIXED_TABLES)
-	if(!tab_gen) { gen_tabs(); tab_gen = 1; }
-	#endif
-
 	INIT(this,
 		.public = {
 			.crypter = {
diff --git a/src/libstrongswan/plugins/af_alg/Makefile.am b/src/libstrongswan/plugins/af_alg/Makefile.am
index 58113ca..bd39853 100644
--- a/src/libstrongswan/plugins/af_alg/Makefile.am
+++ b/src/libstrongswan/plugins/af_alg/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-af-alg.la
diff --git a/src/libstrongswan/plugins/af_alg/Makefile.in b/src/libstrongswan/plugins/af_alg/Makefile.in
index 08f5e94..c338356 100644
--- a/src/libstrongswan/plugins/af_alg/Makefile.in
+++ b/src/libstrongswan/plugins/af_alg/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-af-alg.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-af-alg.la
diff --git a/src/libstrongswan/plugins/agent/Makefile.am b/src/libstrongswan/plugins/agent/Makefile.am
index e60d193..9846213 100644
--- a/src/libstrongswan/plugins/agent/Makefile.am
+++ b/src/libstrongswan/plugins/agent/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-agent.la
diff --git a/src/libstrongswan/plugins/agent/Makefile.in b/src/libstrongswan/plugins/agent/Makefile.in
index bfd9f2b..d009baf 100644
--- a/src/libstrongswan/plugins/agent/Makefile.in
+++ b/src/libstrongswan/plugins/agent/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-agent.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-agent.la
diff --git a/src/libstrongswan/plugins/blowfish/Makefile.am b/src/libstrongswan/plugins/blowfish/Makefile.am
index 3e5cf8f..9c04f56 100644
--- a/src/libstrongswan/plugins/blowfish/Makefile.am
+++ b/src/libstrongswan/plugins/blowfish/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-blowfish.la
diff --git a/src/libstrongswan/plugins/blowfish/Makefile.in b/src/libstrongswan/plugins/blowfish/Makefile.in
index 1e3f69f..396f3a0 100644
--- a/src/libstrongswan/plugins/blowfish/Makefile.in
+++ b/src/libstrongswan/plugins/blowfish/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-blowfish.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-blowfish.la
diff --git a/src/libstrongswan/plugins/ccm/Makefile.am b/src/libstrongswan/plugins/ccm/Makefile.am
index d512f5a..f67c7f9 100644
--- a/src/libstrongswan/plugins/ccm/Makefile.am
+++ b/src/libstrongswan/plugins/ccm/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-ccm.la
diff --git a/src/libstrongswan/plugins/ccm/Makefile.in b/src/libstrongswan/plugins/ccm/Makefile.in
index b1e0f16..a148931 100644
--- a/src/libstrongswan/plugins/ccm/Makefile.in
+++ b/src/libstrongswan/plugins/ccm/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-ccm.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-ccm.la
diff --git a/src/libstrongswan/plugins/cmac/Makefile.am b/src/libstrongswan/plugins/cmac/Makefile.am
index 08e910b..8e0a450 100644
--- a/src/libstrongswan/plugins/cmac/Makefile.am
+++ b/src/libstrongswan/plugins/cmac/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-cmac.la
diff --git a/src/libstrongswan/plugins/cmac/Makefile.in b/src/libstrongswan/plugins/cmac/Makefile.in
index a609e71..cb7965a 100644
--- a/src/libstrongswan/plugins/cmac/Makefile.in
+++ b/src/libstrongswan/plugins/cmac/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-cmac.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-cmac.la
diff --git a/src/libstrongswan/plugins/constraints/Makefile.am b/src/libstrongswan/plugins/constraints/Makefile.am
index 8afde70..2183582 100644
--- a/src/libstrongswan/plugins/constraints/Makefile.am
+++ b/src/libstrongswan/plugins/constraints/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-constraints.la
diff --git a/src/libstrongswan/plugins/constraints/Makefile.in b/src/libstrongswan/plugins/constraints/Makefile.in
index 654800b..34cc2aa 100644
--- a/src/libstrongswan/plugins/constraints/Makefile.in
+++ b/src/libstrongswan/plugins/constraints/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-constraints.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-constraints.la
diff --git a/src/libstrongswan/plugins/ctr/Makefile.am b/src/libstrongswan/plugins/ctr/Makefile.am
index 52278b6..abee58e 100644
--- a/src/libstrongswan/plugins/ctr/Makefile.am
+++ b/src/libstrongswan/plugins/ctr/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-ctr.la
diff --git a/src/libstrongswan/plugins/ctr/Makefile.in b/src/libstrongswan/plugins/ctr/Makefile.in
index b6789e7..8582937 100644
--- a/src/libstrongswan/plugins/ctr/Makefile.in
+++ b/src/libstrongswan/plugins/ctr/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-ctr.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-ctr.la
diff --git a/src/libstrongswan/plugins/curl/Makefile.am b/src/libstrongswan/plugins/curl/Makefile.am
index 17bcc8d..a22f9b3 100644
--- a/src/libstrongswan/plugins/curl/Makefile.am
+++ b/src/libstrongswan/plugins/curl/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-curl.la
diff --git a/src/libstrongswan/plugins/curl/Makefile.in b/src/libstrongswan/plugins/curl/Makefile.in
index 67a92b3..c34d349 100644
--- a/src/libstrongswan/plugins/curl/Makefile.in
+++ b/src/libstrongswan/plugins/curl/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-curl.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-curl.la
diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c
index 644f277..620cf74 100644
--- a/src/libstrongswan/plugins/curl/curl_fetcher.c
+++ b/src/libstrongswan/plugins/curl/curl_fetcher.c
@@ -50,6 +50,11 @@ struct private_curl_fetcher_t {
 	fetcher_callback_t cb;
 
 	/**
+	 * Variable that receives the response code
+	 */
+	u_int *result;
+
+	/**
 	 * Timeout for a transfer
 	 */
 	long timeout;
@@ -82,6 +87,7 @@ METHOD(fetcher_t, fetch, status_t,
 {
 	char error[CURL_ERROR_SIZE], *enc_uri;
 	status_t status;
+	long result = 0;
 	cb_data_t data = {
 		.cb = this->cb,
 		.user = userdata,
@@ -102,7 +108,7 @@ METHOD(fetcher_t, fetch, status_t,
 		goto out;
 	}
 	curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error);
-	curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
+	curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, FALSE);
 	curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
 	if (this->timeout)
 	{
@@ -123,7 +129,13 @@ METHOD(fetcher_t, fetch, status_t,
 			status = NOT_SUPPORTED;
 			break;
 		case CURLE_OK:
-			status = SUCCESS;
+			curl_easy_getinfo(this->curl, CURLINFO_RESPONSE_CODE,
+							  &result);
+			if (this->result)
+			{
+				*this->result = result;
+			}
+			status = (result >= 200 && result < 300) ? SUCCESS : FAILED;
 			break;
 		default:
 			DBG1(DBG_LIB, "libcurl http request failed: %s", error);
@@ -188,6 +200,11 @@ METHOD(fetcher_t, set_option, bool,
 			this->cb = va_arg(args, fetcher_callback_t);
 			break;
 		}
+		case FETCH_RESPONSE_CODE:
+		{
+			this->result = va_arg(args, u_int*);
+			break;
+		}
 		case FETCH_SOURCEIP:
 		{
 			char buf[64];
diff --git a/src/libstrongswan/plugins/des/Makefile.am b/src/libstrongswan/plugins/des/Makefile.am
index 9ca9659..87fbcb1 100644
--- a/src/libstrongswan/plugins/des/Makefile.am
+++ b/src/libstrongswan/plugins/des/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-des.la
diff --git a/src/libstrongswan/plugins/des/Makefile.in b/src/libstrongswan/plugins/des/Makefile.in
index fb38b07..2f8eb85 100644
--- a/src/libstrongswan/plugins/des/Makefile.in
+++ b/src/libstrongswan/plugins/des/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-des.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-des.la
diff --git a/src/libstrongswan/plugins/dnskey/Makefile.am b/src/libstrongswan/plugins/dnskey/Makefile.am
index 7e74fd8..47f4327 100644
--- a/src/libstrongswan/plugins/dnskey/Makefile.am
+++ b/src/libstrongswan/plugins/dnskey/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-dnskey.la
diff --git a/src/libstrongswan/plugins/dnskey/Makefile.in b/src/libstrongswan/plugins/dnskey/Makefile.in
index 6986a81..bd6e64b 100644
--- a/src/libstrongswan/plugins/dnskey/Makefile.in
+++ b/src/libstrongswan/plugins/dnskey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-dnskey.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-dnskey.la
diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.am b/src/libstrongswan/plugins/fips_prf/Makefile.am
index a7ae612..f7e7e1a 100644
--- a/src/libstrongswan/plugins/fips_prf/Makefile.am
+++ b/src/libstrongswan/plugins/fips_prf/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-fips-prf.la
diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.in b/src/libstrongswan/plugins/fips_prf/Makefile.in
index 71a61f6..cc146d8 100644
--- a/src/libstrongswan/plugins/fips_prf/Makefile.in
+++ b/src/libstrongswan/plugins/fips_prf/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-fips-prf.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-fips-prf.la
diff --git a/src/libstrongswan/plugins/gcm/Makefile.am b/src/libstrongswan/plugins/gcm/Makefile.am
index 228b470..5cfeaf7 100644
--- a/src/libstrongswan/plugins/gcm/Makefile.am
+++ b/src/libstrongswan/plugins/gcm/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-gcm.la
diff --git a/src/libstrongswan/plugins/gcm/Makefile.in b/src/libstrongswan/plugins/gcm/Makefile.in
index dbf9d11..4e0e86c 100644
--- a/src/libstrongswan/plugins/gcm/Makefile.in
+++ b/src/libstrongswan/plugins/gcm/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-gcm.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-gcm.la
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.am b/src/libstrongswan/plugins/gcrypt/Makefile.am
index 1a9d225..24a5a9c 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.am
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-gcrypt.la
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in
index 731375d..90990cf 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.in
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-gcrypt.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-gcrypt.la
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
index 44f3f84..f4254bb 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
@@ -28,6 +28,7 @@
 
 #include <errno.h>
 #include <gcrypt.h>
+#include <pthread.h>
 
 typedef struct private_gcrypt_plugin_t private_gcrypt_plugin_t;
 
@@ -43,55 +44,9 @@ struct private_gcrypt_plugin_t {
 };
 
 /**
- * gcrypt mutex initialization wrapper
+ * Define gcrypt multi-threading callbacks as gcry_threads_pthread
  */
-static int mutex_init(void **lock)
-{
-	*lock = mutex_create(MUTEX_TYPE_DEFAULT);
-	return 0;
-}
-
-/**
- * gcrypt mutex cleanup wrapper
- */
-static int mutex_destroy(void **lock)
-{
-	mutex_t *mutex = *lock;
-
-	mutex->destroy(mutex);
-	return 0;
-}
-
-/**
- * gcrypt mutex lock wrapper
- */
-static int mutex_lock(void **lock)
-{
-	mutex_t *mutex = *lock;
-
-	mutex->lock(mutex);
-	return 0;
-}
-
-/**
- * gcrypt mutex unlock wrapper
- */
-static int mutex_unlock(void **lock)
-{
-	mutex_t *mutex = *lock;
-
-	mutex->unlock(mutex);
-	return 0;
-}
-
-/**
- * gcrypt locking functions using our mutex_t
- */
-static struct gcry_thread_cbs thread_functions = {
-	GCRY_THREAD_OPTION_USER, NULL,
-	mutex_init, mutex_destroy, mutex_lock, mutex_unlock,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
 
 METHOD(plugin_t, get_name, char*,
 	private_gcrypt_plugin_t *this)
@@ -184,7 +139,7 @@ plugin_t *gcrypt_plugin_create()
 {
 	private_gcrypt_plugin_t *this;
 
-	gcry_control(GCRYCTL_SET_THREAD_CBS, &thread_functions);
+	gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
 
 	if (!gcry_check_version(GCRYPT_VERSION))
 	{
@@ -213,4 +168,3 @@ plugin_t *gcrypt_plugin_create()
 
 	return &this->public.plugin;
 }
-
diff --git a/src/libstrongswan/plugins/gmp/Makefile.am b/src/libstrongswan/plugins/gmp/Makefile.am
index 57e1fd7..a2cfefd 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.am
+++ b/src/libstrongswan/plugins/gmp/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-gmp.la
diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in
index 6b63e19..c13f4e5 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.in
+++ b/src/libstrongswan/plugins/gmp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-gmp.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-gmp.la
diff --git a/src/libstrongswan/plugins/hmac/Makefile.am b/src/libstrongswan/plugins/hmac/Makefile.am
index 5d88d26..65c36b2 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.am
+++ b/src/libstrongswan/plugins/hmac/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-hmac.la
diff --git a/src/libstrongswan/plugins/hmac/Makefile.in b/src/libstrongswan/plugins/hmac/Makefile.in
index d255cc9..cdfa94c 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.in
+++ b/src/libstrongswan/plugins/hmac/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-hmac.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-hmac.la
diff --git a/src/libstrongswan/plugins/keychain/Makefile.am b/src/libstrongswan/plugins/keychain/Makefile.am
index bd04db3..07d2bcd 100644
--- a/src/libstrongswan/plugins/keychain/Makefile.am
+++ b/src/libstrongswan/plugins/keychain/Makefile.am
@@ -1,7 +1,7 @@
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan
 
-AM_CFLAGS = -rdynamic
+AM_CFLAGS = $(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-keychain.la
diff --git a/src/libstrongswan/plugins/keychain/Makefile.in b/src/libstrongswan/plugins/keychain/Makefile.in
index 38a478b..2a968b8 100644
--- a/src/libstrongswan/plugins/keychain/Makefile.in
+++ b/src/libstrongswan/plugins/keychain/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ urandom_device = @urandom_device@
 xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan
-AM_CFLAGS = -rdynamic
+AM_CFLAGS = $(PLUGIN_CFLAGS)
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-keychain.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-keychain.la
 libstrongswan_keychain_la_SOURCES = \
diff --git a/src/libstrongswan/plugins/ldap/Makefile.am b/src/libstrongswan/plugins/ldap/Makefile.am
index 3bcef1a..333d974 100644
--- a/src/libstrongswan/plugins/ldap/Makefile.am
+++ b/src/libstrongswan/plugins/ldap/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-ldap.la
diff --git a/src/libstrongswan/plugins/ldap/Makefile.in b/src/libstrongswan/plugins/ldap/Makefile.in
index bd5bd43..b8e1b49 100644
--- a/src/libstrongswan/plugins/ldap/Makefile.in
+++ b/src/libstrongswan/plugins/ldap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-ldap.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-ldap.la
diff --git a/src/libstrongswan/plugins/md4/Makefile.am b/src/libstrongswan/plugins/md4/Makefile.am
index a2fe8ec..7130574 100644
--- a/src/libstrongswan/plugins/md4/Makefile.am
+++ b/src/libstrongswan/plugins/md4/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-md4.la
diff --git a/src/libstrongswan/plugins/md4/Makefile.in b/src/libstrongswan/plugins/md4/Makefile.in
index a5caf8d..3de733c 100644
--- a/src/libstrongswan/plugins/md4/Makefile.in
+++ b/src/libstrongswan/plugins/md4/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-md4.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-md4.la
diff --git a/src/libstrongswan/plugins/md5/Makefile.am b/src/libstrongswan/plugins/md5/Makefile.am
index fc6406a..0711160 100644
--- a/src/libstrongswan/plugins/md5/Makefile.am
+++ b/src/libstrongswan/plugins/md5/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-md5.la
diff --git a/src/libstrongswan/plugins/md5/Makefile.in b/src/libstrongswan/plugins/md5/Makefile.in
index c448931..1636b96 100644
--- a/src/libstrongswan/plugins/md5/Makefile.in
+++ b/src/libstrongswan/plugins/md5/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-md5.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-md5.la
diff --git a/src/libstrongswan/plugins/mysql/Makefile.am b/src/libstrongswan/plugins/mysql/Makefile.am
index 588b799..11711b3 100644
--- a/src/libstrongswan/plugins/mysql/Makefile.am
+++ b/src/libstrongswan/plugins/mysql/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	$(MYSQLCFLAG) \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-mysql.la
diff --git a/src/libstrongswan/plugins/mysql/Makefile.in b/src/libstrongswan/plugins/mysql/Makefile.in
index fb36d16..ebd0d90 100644
--- a/src/libstrongswan/plugins/mysql/Makefile.in
+++ b/src/libstrongswan/plugins/mysql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	$(MYSQLCFLAG) \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-mysql.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-mysql.la
diff --git a/src/libstrongswan/plugins/mysql/mysql_database.c b/src/libstrongswan/plugins/mysql/mysql_database.c
index 373e9dc..871cc59 100644
--- a/src/libstrongswan/plugins/mysql/mysql_database.c
+++ b/src/libstrongswan/plugins/mysql/mysql_database.c
@@ -14,12 +14,12 @@
  * for more details.
  */
 
+#include "mysql_database.h"
+
 #define _GNU_SOURCE
 #include <string.h>
 #include <mysql.h>
 
-#include "mysql_database.h"
-
 #include <utils/debug.h>
 #include <utils/chunk.h>
 #include <threading/thread_value.h>
@@ -730,7 +730,7 @@ static bool finalize_transaction(private_mysql_database_t *this,
 	return TRUE;
 }
 
-METHOD(database_t, commit, bool,
+METHOD(database_t, commit_, bool,
 	private_mysql_database_t *this)
 {
 	return finalize_transaction(this, FALSE);
@@ -768,7 +768,7 @@ static bool parse_uri(private_mysql_database_t *this, char *uri)
 	/**
 	 * parse mysql://username:pass@host:port/database uri
 	 */
-	username = strdupa(uri + 8);
+	username = strdup(uri + 8);
 	pos = strchr(username, ':');
 	if (pos)
 	{
@@ -800,10 +800,12 @@ static bool parse_uri(private_mysql_database_t *this, char *uri)
 				this->password = strdup(password);
 				this->database = strdup(database);
 				this->port = atoi(port);
+				free(username);
 				return TRUE;
 			}
 		}
 	}
+	free(username);
 	DBG1(DBG_LIB, "parsing MySQL database uri '%s' failed", uri);
 	return FALSE;
 }
@@ -828,7 +830,7 @@ mysql_database_t *mysql_database_create(char *uri)
 				.query = _query,
 				.execute = _execute,
 				.transaction = _transaction,
-				.commit = _commit,
+				.commit = _commit_,
 				.rollback = _rollback,
 				.get_driver = _get_driver,
 				.destroy = _destroy,
diff --git a/src/libstrongswan/plugins/mysql/mysql_database.h b/src/libstrongswan/plugins/mysql/mysql_database.h
index 98ddcad..bbf6a33 100644
--- a/src/libstrongswan/plugins/mysql/mysql_database.h
+++ b/src/libstrongswan/plugins/mysql/mysql_database.h
@@ -21,6 +21,7 @@
 #ifndef MYSQL_DATABASE_H_
 #define MYSQL_DATABASE_H_
 
+#include <library.h>
 #include <database/database.h>
 
 typedef struct mysql_database_t mysql_database_t;
diff --git a/src/libstrongswan/plugins/nonce/Makefile.am b/src/libstrongswan/plugins/nonce/Makefile.am
index 7dde99e..49dd3e2 100644
--- a/src/libstrongswan/plugins/nonce/Makefile.am
+++ b/src/libstrongswan/plugins/nonce/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-nonce.la
diff --git a/src/libstrongswan/plugins/nonce/Makefile.in b/src/libstrongswan/plugins/nonce/Makefile.in
index 60e45db..f75fbe2 100644
--- a/src/libstrongswan/plugins/nonce/Makefile.in
+++ b/src/libstrongswan/plugins/nonce/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-nonce.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-nonce.la
diff --git a/src/libstrongswan/plugins/ntru/Makefile.am b/src/libstrongswan/plugins/ntru/Makefile.am
index e241554..b959afa 100644
--- a/src/libstrongswan/plugins/ntru/Makefile.am
+++ b/src/libstrongswan/plugins/ntru/Makefile.am
@@ -2,7 +2,8 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic @COVERAGE_CFLAGS@
+	$(PLUGIN_CFLAGS) \
+	@COVERAGE_CFLAGS@
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-ntru.la
@@ -23,5 +24,3 @@ libstrongswan_ntru_la_SOURCES = \
 	ntru_trits.h ntru_trits.c
 
 libstrongswan_ntru_la_LDFLAGS = -module -avoid-version
-
-
diff --git a/src/libstrongswan/plugins/ntru/Makefile.in b/src/libstrongswan/plugins/ntru/Makefile.in
index 3825804..fa10c83 100644
--- a/src/libstrongswan/plugins/ntru/Makefile.in
+++ b/src/libstrongswan/plugins/ntru/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,8 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic @COVERAGE_CFLAGS@
+	$(PLUGIN_CFLAGS) \
+	@COVERAGE_CFLAGS@
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-ntru.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-ntru.la
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am
index cbfd69b..9287f78 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.am
+++ b/src/libstrongswan/plugins/openssl/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 	-DFIPS_MODE=${fips_mode}
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-openssl.la
@@ -32,4 +32,4 @@ libstrongswan_openssl_la_SOURCES = \
 	openssl_gcm.c openssl_gcm.h
 
 libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
-libstrongswan_openssl_la_LIBADD  = -lcrypto
+libstrongswan_openssl_la_LIBADD  = $(OPENSSL_LIB)
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in
index 5d8ada2..6f0a3bf 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.in
+++ b/src/libstrongswan/plugins/openssl/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -127,7 +127,8 @@ am__uninstall_files_from_dir = { \
   }
 am__installdirs = "$(DESTDIR)$(plugindir)"
 LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
-libstrongswan_openssl_la_DEPENDENCIES =
+am__DEPENDENCIES_1 =
+libstrongswan_openssl_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
 am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \
 	openssl_util.lo openssl_crypter.lo openssl_hasher.lo \
 	openssl_sha1_prf.lo openssl_diffie_hellman.lo \
@@ -272,6 +273,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -290,6 +292,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -317,6 +320,7 @@ 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@
@@ -408,6 +412,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -423,7 +428,7 @@ AM_CPPFLAGS = \
 	-DFIPS_MODE=${fips_mode}
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-openssl.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-openssl.la
@@ -448,7 +453,7 @@ libstrongswan_openssl_la_SOURCES = \
 	openssl_gcm.c openssl_gcm.h
 
 libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
-libstrongswan_openssl_la_LIBADD = -lcrypto
+libstrongswan_openssl_la_LIBADD = $(OPENSSL_LIB)
 all: all-am
 
 .SUFFIXES:
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index f4aef82..a426cdc 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -14,6 +14,12 @@
  * for more details.
  */
 
+#include <library.h>
+#include <utils/debug.h>
+#include <threading/thread.h>
+#include <threading/mutex.h>
+#include <threading/thread_value.h>
+
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/conf.h>
@@ -24,12 +30,6 @@
 #endif
 
 #include "openssl_plugin.h"
-
-#include <library.h>
-#include <utils/debug.h>
-#include <threading/thread.h>
-#include <threading/mutex.h>
-#include <threading/thread_value.h>
 #include "openssl_util.h"
 #include "openssl_crypter.h"
 #include "openssl_hasher.h"
@@ -526,9 +526,10 @@ plugin_t *openssl_plugin_create()
 #ifdef OPENSSL_FIPS
 	if (fips_mode)
 	{
-		if (!FIPS_mode_set(fips_mode))
+		if (FIPS_mode() != fips_mode && !FIPS_mode_set(fips_mode))
 		{
-			DBG1(DBG_LIB, "unable to set openssl FIPS mode(%d)", fips_mode);
+			DBG1(DBG_LIB, "unable to set openssl FIPS mode(%d) from (%d)",
+				 fips_mode, FIPS_mode());
 			return NULL;
 		}
 	}
@@ -558,8 +559,8 @@ plugin_t *openssl_plugin_create()
 #ifdef OPENSSL_FIPS
 	/* we do this here as it may have been enabled via openssl.conf */
 	fips_mode = FIPS_mode();
-	DBG1(DBG_LIB, "openssl FIPS mode(%d) - %sabled ", fips_mode,
-		 fips_mode ? "en" : "dis");
+	dbg(DBG_LIB, strpfx(lib->ns, "charon") ? 1 : 2,
+		"openssl FIPS mode(%d) - %sabled ", fips_mode, fips_mode ? "en" : "dis");
 #endif /* OPENSSL_FIPS */
 
 #ifndef OPENSSL_NO_ENGINE
diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c
index 815cf4f..c807bb6 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rng.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rng.c
@@ -20,7 +20,9 @@
  * THE SOFTWARE.
  */
 
+#include <library.h>
 #include <utils/debug.h>
+
 #include <openssl/rand.h>
 #include <openssl/err.h>
 
diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h
index ce2a9e1..2db0731 100644
--- a/src/libstrongswan/plugins/openssl/openssl_util.h
+++ b/src/libstrongswan/plugins/openssl/openssl_util.h
@@ -22,6 +22,12 @@
 #define OPENSSL_UTIL_H_
 
 #include <library.h>
+
+#ifdef X509_NAME
+/* from <wincrypt.h> */
+# undef X509_NAME
+#endif
+
 #include <openssl/bn.h>
 #include <openssl/asn1.h>
 
diff --git a/src/libstrongswan/plugins/padlock/Makefile.am b/src/libstrongswan/plugins/padlock/Makefile.am
index 0acd838..1110a2e 100644
--- a/src/libstrongswan/plugins/padlock/Makefile.am
+++ b/src/libstrongswan/plugins/padlock/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-padlock.la
diff --git a/src/libstrongswan/plugins/padlock/Makefile.in b/src/libstrongswan/plugins/padlock/Makefile.in
index 0450ab0..39ee773 100644
--- a/src/libstrongswan/plugins/padlock/Makefile.in
+++ b/src/libstrongswan/plugins/padlock/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-padlock.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-padlock.la
diff --git a/src/libstrongswan/plugins/pem/Makefile.am b/src/libstrongswan/plugins/pem/Makefile.am
index 9aa853e..55e5251 100644
--- a/src/libstrongswan/plugins/pem/Makefile.am
+++ b/src/libstrongswan/plugins/pem/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pem.la
diff --git a/src/libstrongswan/plugins/pem/Makefile.in b/src/libstrongswan/plugins/pem/Makefile.in
index 300615e..28d0f84 100644
--- a/src/libstrongswan/plugins/pem/Makefile.in
+++ b/src/libstrongswan/plugins/pem/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pem.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pem.la
diff --git a/src/libstrongswan/plugins/pgp/Makefile.am b/src/libstrongswan/plugins/pgp/Makefile.am
index d3eef3c..093e94b 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.am
+++ b/src/libstrongswan/plugins/pgp/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pgp.la
diff --git a/src/libstrongswan/plugins/pgp/Makefile.in b/src/libstrongswan/plugins/pgp/Makefile.in
index ca8743b..29387a3 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.in
+++ b/src/libstrongswan/plugins/pgp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pgp.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pgp.la
diff --git a/src/libstrongswan/plugins/pgp/pgp_builder.c b/src/libstrongswan/plugins/pgp/pgp_builder.c
index 3ff3572..152e83a 100644
--- a/src/libstrongswan/plugins/pgp/pgp_builder.c
+++ b/src/libstrongswan/plugins/pgp/pgp_builder.c
@@ -17,7 +17,7 @@
 #include "pgp_builder.h"
 #include "pgp_utils.h"
 
-#include <utils/enum.h>
+#include <utils/utils.h>
 #include <utils/debug.h>
 #include <credentials/keys/private_key.h>
 
@@ -273,4 +273,3 @@ private_key_t *pgp_private_key_load(key_type_t type, va_list args)
 			return NULL;
 	}
 }
-
diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.am b/src/libstrongswan/plugins/pkcs1/Makefile.am
index 5dbc4e9..d579531 100644
--- a/src/libstrongswan/plugins/pkcs1/Makefile.am
+++ b/src/libstrongswan/plugins/pkcs1/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pkcs1.la
diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.in b/src/libstrongswan/plugins/pkcs1/Makefile.in
index c563806..edaa8c3 100644
--- a/src/libstrongswan/plugins/pkcs1/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs1/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pkcs1.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pkcs1.la
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
index 2c3bf6e..905f14c 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
@@ -30,8 +30,8 @@ static bool build_pub(chunk_t *encoding, va_list args)
 						   CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
 	{
 		*encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
-						asn1_wrap(ASN1_INTEGER, "c", n),
-						asn1_wrap(ASN1_INTEGER, "c", e));
+						asn1_integer("c", n),
+						asn1_integer("c", e));
 		return TRUE;
 	}
 	return FALSE;
@@ -51,8 +51,29 @@ static bool build_pub_info(chunk_t *encoding, va_list args)
 						asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
 						asn1_bitstring("m",
 							asn1_wrap(ASN1_SEQUENCE, "mm",
-								asn1_wrap(ASN1_INTEGER, "c", n),
-								asn1_wrap(ASN1_INTEGER, "c", e))));
+								asn1_integer("c", n),
+								asn1_integer("c", e))));
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Encode the RSA modulus of a public key only
+ */
+static bool build_pub_modulus(chunk_t *encoding, va_list args)
+{
+	chunk_t n;
+
+	if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n, CRED_PART_END))
+	{
+		/* remove preceding zero bytes */
+		while (n.len > 0 && *n.ptr == 0x00)
+		{
+			n.ptr++;
+			n.len--;
+		}
+		*encoding = chunk_clone(n);
 		return TRUE;
 	}
 	return FALSE;
@@ -73,14 +94,14 @@ static bool build_priv(chunk_t *encoding, va_list args)
 	{
 		*encoding = asn1_wrap(ASN1_SEQUENCE, "cmmssssss",
 						ASN1_INTEGER_0,
-						asn1_wrap(ASN1_INTEGER, "c", n),
-						asn1_wrap(ASN1_INTEGER, "c", e),
-						asn1_wrap(ASN1_INTEGER, "c", d),
-						asn1_wrap(ASN1_INTEGER, "c", p),
-						asn1_wrap(ASN1_INTEGER, "c", q),
-						asn1_wrap(ASN1_INTEGER, "c", exp1),
-						asn1_wrap(ASN1_INTEGER, "c", exp2),
-						asn1_wrap(ASN1_INTEGER, "c", coeff));
+						asn1_integer("c", n),
+						asn1_integer("c", e),
+						asn1_integer("c", d),
+						asn1_integer("c", p),
+						asn1_integer("c", q),
+						asn1_integer("c", exp1),
+						asn1_integer("c", exp2),
+						asn1_integer("c", coeff));
 		return TRUE;
 	}
 	return FALSE;
@@ -151,6 +172,8 @@ bool pkcs1_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
 			return build_pub(encoding, args);
 		case PUBKEY_SPKI_ASN1_DER:
 			return build_pub_info(encoding, args);
+		case PUBKEY_RSA_MODULUS:
+			return build_pub_modulus(encoding, args);
 		case PRIVKEY_ASN1_DER:
 			return build_priv(encoding, args);
 		default:
diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.am b/src/libstrongswan/plugins/pkcs11/Makefile.am
index 1d175ec..a2a1bcf 100644
--- a/src/libstrongswan/plugins/pkcs11/Makefile.am
+++ b/src/libstrongswan/plugins/pkcs11/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pkcs11.la
diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.in b/src/libstrongswan/plugins/pkcs11/Makefile.in
index 5d2f39c..55df269 100644
--- a/src/libstrongswan/plugins/pkcs11/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs11/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pkcs11.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pkcs11.la
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h
index abd99ed..b8b4ff7 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h
@@ -29,7 +29,7 @@ typedef struct pkcs11_library_t pkcs11_library_t;
 
 #include "pkcs11.h"
 
-#include <utils/enum.h>
+#include <utils/utils.h>
 #include <utils/chunk.h>
 #include <collections/enumerator.h>
 
diff --git a/src/libstrongswan/plugins/pkcs12/Makefile.am b/src/libstrongswan/plugins/pkcs12/Makefile.am
index af472ba..8078ff3 100644
--- a/src/libstrongswan/plugins/pkcs12/Makefile.am
+++ b/src/libstrongswan/plugins/pkcs12/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pkcs12.la
diff --git a/src/libstrongswan/plugins/pkcs12/Makefile.in b/src/libstrongswan/plugins/pkcs12/Makefile.in
index f398652..f4d399c 100644
--- a/src/libstrongswan/plugins/pkcs12/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs12/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pkcs12.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pkcs12.la
diff --git a/src/libstrongswan/plugins/pkcs7/Makefile.am b/src/libstrongswan/plugins/pkcs7/Makefile.am
index 080947f..f69176a 100644
--- a/src/libstrongswan/plugins/pkcs7/Makefile.am
+++ b/src/libstrongswan/plugins/pkcs7/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pkcs7.la
diff --git a/src/libstrongswan/plugins/pkcs7/Makefile.in b/src/libstrongswan/plugins/pkcs7/Makefile.in
index 7d1c655..4b60cad 100644
--- a/src/libstrongswan/plugins/pkcs7/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs7/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -267,6 +267,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -285,6 +286,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -312,6 +314,7 @@ 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@
@@ -403,6 +406,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pkcs7.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pkcs7.la
diff --git a/src/libstrongswan/plugins/pkcs8/Makefile.am b/src/libstrongswan/plugins/pkcs8/Makefile.am
index 98e3263..88a205a 100644
--- a/src/libstrongswan/plugins/pkcs8/Makefile.am
+++ b/src/libstrongswan/plugins/pkcs8/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pkcs8.la
diff --git a/src/libstrongswan/plugins/pkcs8/Makefile.in b/src/libstrongswan/plugins/pkcs8/Makefile.in
index fca8fd1..bf0a0cc 100644
--- a/src/libstrongswan/plugins/pkcs8/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs8/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pkcs8.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pkcs8.la
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index 487fafa..c23f2f0 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -21,7 +21,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <string.h>
+#ifdef HAVE_DLADDR
 #include <dlfcn.h>
+#endif
 #include <limits.h>
 #include <stdio.h>
 
diff --git a/src/libstrongswan/plugins/pubkey/Makefile.am b/src/libstrongswan/plugins/pubkey/Makefile.am
index 4f23544..5a78bf2 100644
--- a/src/libstrongswan/plugins/pubkey/Makefile.am
+++ b/src/libstrongswan/plugins/pubkey/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-pubkey.la
diff --git a/src/libstrongswan/plugins/pubkey/Makefile.in b/src/libstrongswan/plugins/pubkey/Makefile.in
index 6f00e7e..2dc355b 100644
--- a/src/libstrongswan/plugins/pubkey/Makefile.in
+++ b/src/libstrongswan/plugins/pubkey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-pubkey.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-pubkey.la
diff --git a/src/libstrongswan/plugins/random/Makefile.am b/src/libstrongswan/plugins/random/Makefile.am
index 7c03c66..b87622c 100644
--- a/src/libstrongswan/plugins/random/Makefile.am
+++ b/src/libstrongswan/plugins/random/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = \
 	-DDEV_URANDOM=\"${urandom_device}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-random.la
diff --git a/src/libstrongswan/plugins/random/Makefile.in b/src/libstrongswan/plugins/random/Makefile.in
index 59f062d..e90c321 100644
--- a/src/libstrongswan/plugins/random/Makefile.in
+++ b/src/libstrongswan/plugins/random/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-DDEV_URANDOM=\"${urandom_device}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-random.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-random.la
diff --git a/src/libstrongswan/plugins/random/random_plugin.c b/src/libstrongswan/plugins/random/random_plugin.c
index 1f10792..e159751 100644
--- a/src/libstrongswan/plugins/random/random_plugin.c
+++ b/src/libstrongswan/plugins/random/random_plugin.c
@@ -89,6 +89,11 @@ static bool open_dev(char *file, int *fd)
 		DBG1(DBG_LIB, "opening \"%s\" failed: %s", file, strerror(errno));
 		return FALSE;
 	}
+	if (fcntl(*fd, F_SETFD, FD_CLOEXEC) == -1)
+	{
+		DBG1(DBG_LIB, "setting FD_CLOEXEC for \"%s\" failed: %s",
+			 file, strerror(errno));
+	}
 	return TRUE;
 }
 
diff --git a/src/libstrongswan/plugins/rc2/Makefile.am b/src/libstrongswan/plugins/rc2/Makefile.am
index 3f89272..edaf90c 100644
--- a/src/libstrongswan/plugins/rc2/Makefile.am
+++ b/src/libstrongswan/plugins/rc2/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-rc2.la
diff --git a/src/libstrongswan/plugins/rc2/Makefile.in b/src/libstrongswan/plugins/rc2/Makefile.in
index b820d12..dd49ea6 100644
--- a/src/libstrongswan/plugins/rc2/Makefile.in
+++ b/src/libstrongswan/plugins/rc2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-rc2.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-rc2.la
diff --git a/src/libstrongswan/plugins/rdrand/Makefile.am b/src/libstrongswan/plugins/rdrand/Makefile.am
index d9cb001..674bc48 100644
--- a/src/libstrongswan/plugins/rdrand/Makefile.am
+++ b/src/libstrongswan/plugins/rdrand/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-rdrand.la
diff --git a/src/libstrongswan/plugins/rdrand/Makefile.in b/src/libstrongswan/plugins/rdrand/Makefile.in
index db926c5..44dce24 100644
--- a/src/libstrongswan/plugins/rdrand/Makefile.in
+++ b/src/libstrongswan/plugins/rdrand/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-rdrand.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-rdrand.la
diff --git a/src/libstrongswan/plugins/revocation/Makefile.am b/src/libstrongswan/plugins/revocation/Makefile.am
index 5bb5ac2..9532d5f 100644
--- a/src/libstrongswan/plugins/revocation/Makefile.am
+++ b/src/libstrongswan/plugins/revocation/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-revocation.la
diff --git a/src/libstrongswan/plugins/revocation/Makefile.in b/src/libstrongswan/plugins/revocation/Makefile.in
index cfdd7e8..cb185e7 100644
--- a/src/libstrongswan/plugins/revocation/Makefile.in
+++ b/src/libstrongswan/plugins/revocation/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-revocation.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-revocation.la
diff --git a/src/libstrongswan/plugins/sha1/Makefile.am b/src/libstrongswan/plugins/sha1/Makefile.am
index f5e7d94..99c9d18 100644
--- a/src/libstrongswan/plugins/sha1/Makefile.am
+++ b/src/libstrongswan/plugins/sha1/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-sha1.la
diff --git a/src/libstrongswan/plugins/sha1/Makefile.in b/src/libstrongswan/plugins/sha1/Makefile.in
index 4f9d24a..f07b768 100644
--- a/src/libstrongswan/plugins/sha1/Makefile.in
+++ b/src/libstrongswan/plugins/sha1/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -414,7 +418,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-sha1.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-sha1.la
diff --git a/src/libstrongswan/plugins/sha1/sha1_hasher.c b/src/libstrongswan/plugins/sha1/sha1_hasher.c
index b0efbae..b51a261 100644
--- a/src/libstrongswan/plugins/sha1/sha1_hasher.c
+++ b/src/libstrongswan/plugins/sha1/sha1_hasher.c
@@ -18,7 +18,8 @@
  */
 
 #include <string.h>
-#include <arpa/inet.h>
+
+#include <library.h>
 
 #include "sha1_hasher.h"
 
@@ -257,4 +258,3 @@ sha1_hasher_t *sha1_hasher_create(hash_algorithm_t algo)
 
 	return &(this->public);
 }
-
diff --git a/src/libstrongswan/plugins/sha1/sha1_prf.c b/src/libstrongswan/plugins/sha1/sha1_prf.c
index cdc494b..cc4924a 100644
--- a/src/libstrongswan/plugins/sha1/sha1_prf.c
+++ b/src/libstrongswan/plugins/sha1/sha1_prf.c
@@ -16,7 +16,7 @@
 #include "sha1_prf.h"
 #include "sha1_hasher.h"
 
-#include <arpa/inet.h>
+#include <library.h>
 
 typedef struct private_sha1_prf_t private_sha1_prf_t;
 typedef struct private_sha1_hasher_t private_sha1_hasher_t;
@@ -148,4 +148,3 @@ sha1_prf_t *sha1_prf_create(pseudo_random_function_t algo)
 
 	return &this->public;
 }
-
diff --git a/src/libstrongswan/plugins/sha2/Makefile.am b/src/libstrongswan/plugins/sha2/Makefile.am
index cdd8696..7233b95 100644
--- a/src/libstrongswan/plugins/sha2/Makefile.am
+++ b/src/libstrongswan/plugins/sha2/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-sha2.la
diff --git a/src/libstrongswan/plugins/sha2/Makefile.in b/src/libstrongswan/plugins/sha2/Makefile.in
index ddc2875..ab95f8a 100644
--- a/src/libstrongswan/plugins/sha2/Makefile.in
+++ b/src/libstrongswan/plugins/sha2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-sha2.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-sha2.la
diff --git a/src/libstrongswan/plugins/soup/Makefile.am b/src/libstrongswan/plugins/soup/Makefile.am
index 8df666f..a600fc0 100644
--- a/src/libstrongswan/plugins/soup/Makefile.am
+++ b/src/libstrongswan/plugins/soup/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	 ${soup_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-soup.la
diff --git a/src/libstrongswan/plugins/soup/Makefile.in b/src/libstrongswan/plugins/soup/Makefile.in
index 2ba05f7..ef85abd 100644
--- a/src/libstrongswan/plugins/soup/Makefile.in
+++ b/src/libstrongswan/plugins/soup/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -264,6 +264,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -282,6 +283,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -309,6 +311,7 @@ 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@
@@ -400,6 +403,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	 ${soup_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-soup.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-soup.la
diff --git a/src/libstrongswan/plugins/soup/soup_fetcher.c b/src/libstrongswan/plugins/soup/soup_fetcher.c
index 681a3c3..99525cb 100644
--- a/src/libstrongswan/plugins/soup/soup_fetcher.c
+++ b/src/libstrongswan/plugins/soup/soup_fetcher.c
@@ -63,6 +63,11 @@ struct private_soup_fetcher_t {
 	 * Fetcher callback function
 	 */
 	fetcher_callback_t cb;
+
+	/**
+	 * Response status
+	 */
+	u_int *result;
 };
 
 /**
@@ -119,12 +124,16 @@ METHOD(fetcher_t, fetch, status_t,
 
 	DBG2(DBG_LIB, "sending http request to '%s'...", uri);
 	soup_session_send_message(data.session, message);
+	if (this->result)
+	{
+		*this->result = message->status_code;
+	}
 	if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
 	{
 		status = SUCCESS;
 	}
-	else
-	{
+	else if (!this->result)
+	{	/* only log an error if the code is not returned */
 		DBG1(DBG_LIB, "HTTP request failed: %s", message->reason_phrase);
 	}
 	g_object_unref(G_OBJECT(message));
@@ -157,6 +166,9 @@ METHOD(fetcher_t, set_option, bool,
 		case FETCH_CALLBACK:
 			this->cb = va_arg(args, fetcher_callback_t);
 			break;
+		case FETCH_RESPONSE_CODE:
+			this->result = va_arg(args, u_int*);
+			break;
 		default:
 			supported = FALSE;
 			break;
diff --git a/src/libstrongswan/plugins/sqlite/Makefile.am b/src/libstrongswan/plugins/sqlite/Makefile.am
index 717d635..0a9b11d 100644
--- a/src/libstrongswan/plugins/sqlite/Makefile.am
+++ b/src/libstrongswan/plugins/sqlite/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-sqlite.la
diff --git a/src/libstrongswan/plugins/sqlite/Makefile.in b/src/libstrongswan/plugins/sqlite/Makefile.in
index 2cbacdd..f7be0e4 100644
--- a/src/libstrongswan/plugins/sqlite/Makefile.in
+++ b/src/libstrongswan/plugins/sqlite/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-sqlite.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-sqlite.la
diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c
index 7b47678..ec1ca14 100644
--- a/src/libstrongswan/plugins/sqlite/sqlite_database.c
+++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c
@@ -101,13 +101,15 @@ static sqlite3_stmt* run(private_sqlite_database_t *this, char *sql,
 				case DB_TEXT:
 				{
 					const char *text = va_arg(*args, const char*);
-					res = sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC);
+					res = sqlite3_bind_text(stmt, i, text, -1,
+											SQLITE_TRANSIENT);
 					break;
 				}
 				case DB_BLOB:
 				{
 					chunk_t c = va_arg(*args, chunk_t);
-					res = sqlite3_bind_blob(stmt, i, c.ptr, c.len, SQLITE_STATIC);
+					res = sqlite3_bind_blob(stmt, i, c.ptr, c.len,
+											SQLITE_TRANSIENT);
 					break;
 				}
 				case DB_DOUBLE:
@@ -365,7 +367,7 @@ static bool finalize_transaction(private_sqlite_database_t *this,
 	return TRUE;
 }
 
-METHOD(database_t, commit, bool,
+METHOD(database_t, commit_, bool,
 	private_sqlite_database_t *this)
 {
 	return finalize_transaction(this, FALSE);
@@ -429,7 +431,7 @@ sqlite_database_t *sqlite_database_create(char *uri)
 				.query = _query,
 				.execute = _execute,
 				.transaction = _transaction,
-				.commit = _commit,
+				.commit = _commit_,
 				.rollback = _rollback,
 				.get_driver = _get_driver,
 				.destroy = _destroy,
diff --git a/src/libstrongswan/plugins/sshkey/Makefile.am b/src/libstrongswan/plugins/sshkey/Makefile.am
index 22c076f..5b86a7e 100644
--- a/src/libstrongswan/plugins/sshkey/Makefile.am
+++ b/src/libstrongswan/plugins/sshkey/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-sshkey.la
diff --git a/src/libstrongswan/plugins/sshkey/Makefile.in b/src/libstrongswan/plugins/sshkey/Makefile.in
index 6bd8250..ed86fca 100644
--- a/src/libstrongswan/plugins/sshkey/Makefile.in
+++ b/src/libstrongswan/plugins/sshkey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -416,7 +420,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-sshkey.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-sshkey.la
diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.c b/src/libstrongswan/plugins/sshkey/sshkey_builder.c
index 6526631..4a9f5b8 100644
--- a/src/libstrongswan/plugins/sshkey/sshkey_builder.c
+++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2013-2014 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -140,8 +140,8 @@ static sshkey_public_key_t *load_from_stream(FILE *file)
 	char line[1024], *token;
 
 	while (!public && fgets(line, sizeof(line), file))
-	{	/* the format is: ssh-[rsa|ecdsa-...] <key(base64)> <identifier> */
-		if (!strpfx(line, "ssh-"))
+	{	/* the format is: ssh-rsa|ecdsa-... <key(base64)> <identifier> */
+		if (!strpfx(line, "ssh-rsa") && !strpfx(line, ECDSA_PREFIX))
 		{
 			continue;
 		}
@@ -235,3 +235,46 @@ sshkey_public_key_t *sshkey_public_key_load(key_type_t type, va_list args)
 	}
 	return NULL;
 }
+
+/**
+ * See header.
+ */
+certificate_t *sshkey_certificate_load(certificate_type_t type, va_list args)
+{
+	certificate_t *cert;
+	public_key_t *key;
+	identification_t *subject = NULL;
+	char *file = NULL;
+
+	while (TRUE)
+	{
+		switch (va_arg(args, builder_part_t))
+		{
+			case BUILD_FROM_FILE:
+				file = va_arg(args, char*);
+				continue;
+			case BUILD_SUBJECT:
+				subject = va_arg(args, identification_t*);
+				continue;
+			case BUILD_END:
+				break;
+			default:
+				return NULL;
+		}
+		break;
+	}
+	if (!file || !subject)
+	{
+		return NULL;
+	}
+	key = (public_key_t*)load_from_file(file);
+	if (!key)
+	{
+		return NULL;
+	}
+	cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+							  CERT_TRUSTED_PUBKEY, BUILD_PUBLIC_KEY, key,
+							  BUILD_SUBJECT, subject, BUILD_END);
+	key->destroy(key);
+	return cert;
+}
diff --git a/src/libstrongswan/plugins/sshkey/sshkey_builder.h b/src/libstrongswan/plugins/sshkey/sshkey_builder.h
index d138c87..20979c2 100644
--- a/src/libstrongswan/plugins/sshkey/sshkey_builder.h
+++ b/src/libstrongswan/plugins/sshkey/sshkey_builder.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2013-2014 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 typedef struct sshkey_public_key_t sshkey_public_key_t;
 
 /**
- * Public key implementation supporting RFC 4253 decoding.
+ * Public key implementation supporting RFC 4253/RFC 5656 decoding.
  */
 struct sshkey_public_key_t {
 
@@ -48,4 +48,15 @@ struct sshkey_public_key_t {
  */
 sshkey_public_key_t *sshkey_public_key_load(key_type_t type, va_list args);
 
+/**
+ * Load a public key in RFC 4253 format as certificate.
+ *
+ * Takes a BUILD_FROM_FILE and BUILD_SUBJECT argument.
+ *
+ * @param type		type of the certificate, must be CERT_TRUSTED_PUBKEY
+ * @param args		builder_part_t argument list
+ * @return			built certificate, NULL on failure
+ */
+certificate_t *sshkey_certificate_load(certificate_type_t type, va_list args);
+
 #endif /** SSHKEY_BUILDER_H_ @}*/
diff --git a/src/libstrongswan/plugins/sshkey/sshkey_plugin.c b/src/libstrongswan/plugins/sshkey/sshkey_plugin.c
index 6409fea..1fde0c6 100644
--- a/src/libstrongswan/plugins/sshkey/sshkey_plugin.c
+++ b/src/libstrongswan/plugins/sshkey/sshkey_plugin.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2013-2014 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -44,6 +44,8 @@ METHOD(plugin_t, get_features, int,
 	static plugin_feature_t f[] = {
 		PLUGIN_REGISTER(PUBKEY, sshkey_public_key_load, FALSE),
 			PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
+		PLUGIN_REGISTER(CERT_DECODE, sshkey_certificate_load, FALSE),
+			PLUGIN_PROVIDE(CERT_DECODE, CERT_TRUSTED_PUBKEY),
 	};
 	*features = f;
 	return countof(f);
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.am b/src/libstrongswan/plugins/test_vectors/Makefile.am
index 6dcad40..85f8672 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.am
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-test-vectors.la
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in
index 7443f53..f517eb4 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.in
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -280,6 +280,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -298,6 +299,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -325,6 +327,7 @@ 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@
@@ -416,6 +419,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -430,7 +434,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-test-vectors.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-test-vectors.la
diff --git a/src/libstrongswan/plugins/unbound/Makefile.am b/src/libstrongswan/plugins/unbound/Makefile.am
index 64a5cc7..b8d9ace 100644
--- a/src/libstrongswan/plugins/unbound/Makefile.am
+++ b/src/libstrongswan/plugins/unbound/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-unbound.la
diff --git a/src/libstrongswan/plugins/unbound/Makefile.in b/src/libstrongswan/plugins/unbound/Makefile.in
index c3c6ed6..1668917 100644
--- a/src/libstrongswan/plugins/unbound/Makefile.in
+++ b/src/libstrongswan/plugins/unbound/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -266,6 +266,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -284,6 +285,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -311,6 +313,7 @@ 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@
@@ -402,6 +405,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -417,7 +421,7 @@ AM_CPPFLAGS = \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\"
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-unbound.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-unbound.la
diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.c b/src/libstrongswan/plugins/unbound/unbound_rr.c
index 97c3b19..fc69eed 100644
--- a/src/libstrongswan/plugins/unbound/unbound_rr.c
+++ b/src/libstrongswan/plugins/unbound/unbound_rr.c
@@ -135,8 +135,8 @@ unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr)
 		return NULL;
 	}
 
-	this->type = ldns_rr_get_type(rr);
-	this->class = ldns_rr_get_class(rr);
+	this->type = (rr_type_t)ldns_rr_get_type(rr);
+	this->class = (rr_class_t)ldns_rr_get_class(rr);
 	this->ttl = ldns_rr_ttl(rr);
 	for(i = 0; i < ldns_rr_rd_count(rr); i++)
 	{
diff --git a/src/libstrongswan/plugins/winhttp/Makefile.am b/src/libstrongswan/plugins/winhttp/Makefile.am
new file mode 100644
index 0000000..f6b00a7
--- /dev/null
+++ b/src/libstrongswan/plugins/winhttp/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-winhttp.la
+else
+plugin_LTLIBRARIES = libstrongswan-winhttp.la
+endif
+
+libstrongswan_winhttp_la_SOURCES = \
+	winhttp_fetcher.c winhttp_fetcher.h \
+	winhttp_plugin.c winhttp_plugin.h
+
+libstrongswan_winhttp_la_LDFLAGS = -module -avoid-version
+libstrongswan_winhttp_la_LIBADD  = -lwinhttp
diff --git a/src/libstrongswan/plugins/winhttp/Makefile.in b/src/libstrongswan/plugins/winhttp/Makefile.in
new file mode 100644
index 0000000..4e4fd57
--- /dev/null
+++ b/src/libstrongswan/plugins/winhttp/Makefile.in
@@ -0,0 +1,766 @@
+# 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/libstrongswan/plugins/winhttp
+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_winhttp_la_DEPENDENCIES =
+am_libstrongswan_winhttp_la_OBJECTS = winhttp_fetcher.lo \
+	winhttp_plugin.lo
+libstrongswan_winhttp_la_OBJECTS =  \
+	$(am_libstrongswan_winhttp_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_winhttp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_winhttp_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_winhttp_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_winhttp_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_winhttp_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_winhttp_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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
+
+AM_CFLAGS = \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-winhttp.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-winhttp.la
+libstrongswan_winhttp_la_SOURCES = \
+	winhttp_fetcher.c winhttp_fetcher.h \
+	winhttp_plugin.c winhttp_plugin.h
+
+libstrongswan_winhttp_la_LDFLAGS = -module -avoid-version
+libstrongswan_winhttp_la_LIBADD = -lwinhttp
+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/libstrongswan/plugins/winhttp/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/libstrongswan/plugins/winhttp/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-winhttp.la: $(libstrongswan_winhttp_la_OBJECTS) $(libstrongswan_winhttp_la_DEPENDENCIES) $(EXTRA_libstrongswan_winhttp_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_winhttp_la_LINK) $(am_libstrongswan_winhttp_la_rpath) $(libstrongswan_winhttp_la_OBJECTS) $(libstrongswan_winhttp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/winhttp_fetcher.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/winhttp_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/libstrongswan/plugins/winhttp/winhttp_fetcher.c b/src/libstrongswan/plugins/winhttp/winhttp_fetcher.c
new file mode 100644
index 0000000..5f0b584
--- /dev/null
+++ b/src/libstrongswan/plugins/winhttp/winhttp_fetcher.c
@@ -0,0 +1,396 @@
+/*
+ * 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 <winsock2.h>
+#include <windows.h>
+#include <winhttp.h>
+
+#include "winhttp_fetcher.h"
+
+#include <library.h>
+
+/**
+ * Timeout for DNS resolution, in ms
+ */
+#define RESOLVE_TIMEOUT 5000
+
+/**
+ * Timeout for TCP connect, in ms
+ */
+#define CONNECT_TIMEOUT 10000
+
+typedef struct private_winhttp_fetcher_t private_winhttp_fetcher_t;
+
+/**
+ * Private data of a winhttp_fetcher_t.
+ */
+struct private_winhttp_fetcher_t {
+
+	/**
+	 * Public interface
+	 */
+	winhttp_fetcher_t public;
+
+	/**
+	 * WinHTTP session handle
+	 */
+	HINTERNET session;
+
+	/**
+	 * POST request data
+	 */
+	chunk_t request;
+
+	/**
+	 * HTTP version string to use
+	 */
+	LPWSTR version;
+
+	/**
+	 * Optional HTTP headers, as allocated LPWSTR
+	 */
+	linked_list_t *headers;
+
+	/**
+	 * Callback function
+	 */
+	fetcher_callback_t cb;
+
+	/**
+	 * Timeout for operations, in ms
+	 */
+	u_long timeout;
+
+	/**
+	 * User pointer to store HTTP status code to
+	 */
+	u_int *result;
+};
+
+/**
+ * Configure and send the HTTP request
+ */
+static bool send_request(private_winhttp_fetcher_t *this, HINTERNET request)
+{
+	WCHAR headers[512] = L"";
+	LPWSTR hdr;
+
+	/* Set timeout. By default, send/receive does not time out */
+	if (!WinHttpSetTimeouts(request, RESOLVE_TIMEOUT, CONNECT_TIMEOUT,
+							this->timeout, this->timeout))
+	{
+		DBG1(DBG_LIB, "opening HTTP request failed: %u", GetLastError());
+		return FALSE;
+	}
+	while (this->headers->remove_first(this->headers, (void**)&hdr) == SUCCESS)
+	{
+		wcsncat(headers, hdr, countof(headers) - wcslen(headers) - 1);
+		if (this->headers->get_count(this->headers))
+		{
+			wcsncat(headers, L"\r\n", countof(headers) - wcslen(headers) - 1);
+		}
+		free(hdr);
+	}
+	if (!WinHttpSendRequest(request, headers, wcslen(headers),
+				this->request.ptr, this->request.len, this->request.len, 0))
+	{
+		DBG1(DBG_LIB, "sending HTTP request failed: %u", GetLastError());
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * Read back result and invoke receive callback
+ */
+static bool read_result(private_winhttp_fetcher_t *this, HINTERNET request,
+						void *user)
+{
+	DWORD received;
+	char buf[1024];
+	u_int32_t code;
+	DWORD codelen = sizeof(code);
+
+	if (!WinHttpReceiveResponse(request, NULL))
+	{
+		DBG1(DBG_LIB, "reading HTTP response header failed: %u", GetLastError());
+		return FALSE;
+	}
+	if (!WinHttpQueryHeaders(request,
+				WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+				NULL, &code, &codelen, NULL))
+	{
+		DBG1(DBG_LIB, "reading HTTP status code failed: %u", GetLastError());
+		return FALSE;
+	}
+	if (this->result)
+	{
+		*this->result = code;
+	}
+	if (code < 200 || code >= 300)
+	{	/* non-successful HTTP status code */
+		if (!this->result)
+		{
+			DBG1(DBG_LIB, "HTTP request failed with status %u", code);
+		}
+		return FALSE;
+	}
+	if (this->cb == fetcher_default_callback)
+	{
+		*(chunk_t*)user = chunk_empty;
+	}
+	while (TRUE)
+	{
+		if (!WinHttpReadData(request, buf, sizeof(buf), &received))
+		{
+			DBG1(DBG_LIB, "reading HTTP response failed: %u", GetLastError());
+			return FALSE;
+		}
+		if (received == 0)
+		{
+			/* end of response */
+			break;
+		}
+		if (!this->cb(user, chunk_create(buf, received)))
+		{
+			DBG1(DBG_LIB, "processing response failed or cancelled");
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * Parse an uri to wide string host and path, optionally set flags and port
+ */
+static bool parse_uri(private_winhttp_fetcher_t *this, char *uri,
+					  LPWSTR host, int hostlen, LPWSTR path, int pathlen,
+					  LPWSTR user, int userlen, LPWSTR pass, int passlen,
+					  DWORD *flags, INTERNET_PORT *port)
+{
+	WCHAR wuri[512], extra[256];
+	URL_COMPONENTS comps = {
+		.dwStructSize = sizeof(URL_COMPONENTS),
+		.lpszHostName = host,
+		.dwHostNameLength = hostlen,
+		.lpszUrlPath = path,
+		.dwUrlPathLength = pathlen,
+		.lpszUserName = user,
+		.dwUserNameLength = userlen,
+		.lpszPassword = pass,
+		.dwPasswordLength = passlen,
+		.lpszExtraInfo = extra,
+		.dwExtraInfoLength = countof(extra),
+	};
+
+	if (!MultiByteToWideChar(CP_THREAD_ACP, 0, uri, -1, wuri, countof(wuri)))
+	{
+		DBG1(DBG_LIB, "converting URI failed: %u", GetLastError());
+		return FALSE;
+	}
+	if (!WinHttpCrackUrl(wuri, 0, ICU_ESCAPE, &comps))
+	{
+		DBG1(DBG_LIB, "cracking URI failed: %u", GetLastError());
+		return FALSE;
+	}
+	if (comps.nScheme == INTERNET_SCHEME_HTTPS)
+	{
+		*flags |= WINHTTP_FLAG_SECURE;
+	}
+	if (comps.dwExtraInfoLength)
+	{
+		wcsncat(path, extra, pathlen - comps.dwUrlPathLength - 1);
+	}
+	if (comps.nPort)
+	{
+		*port = comps.nPort;
+	}
+	return TRUE;
+}
+
+/**
+ * Set credentials for basic authentication, if given
+ */
+static bool set_credentials(private_winhttp_fetcher_t *this,
+							HINTERNET *request, LPWSTR user, LPWSTR pass)
+{
+	if (!wcslen(user) && !wcslen(pass))
+	{	/* skip */
+		return TRUE;
+	}
+	return WinHttpSetCredentials(request, WINHTTP_AUTH_TARGET_SERVER,
+								 WINHTTP_AUTH_SCHEME_BASIC, user, pass, NULL);
+}
+
+METHOD(fetcher_t, fetch, status_t,
+	private_winhttp_fetcher_t *this, char *uri, void *userdata)
+{
+	INTERNET_PORT port = INTERNET_DEFAULT_PORT;
+	status_t status = FAILED;
+	DWORD flags = 0;
+	HINTERNET connection, request;
+	WCHAR host[256], path[512], user[256], pass[256], *method;
+
+	if (this->request.len)
+	{
+		method = L"POST";
+	}
+	else
+	{
+		method = L"GET";
+	}
+
+	if (this->result)
+	{	/* zero-initialize for early failures */
+		*this->result = 0;
+	}
+
+	if (parse_uri(this, uri, host, countof(host), path, countof(path),
+				  user, countof(user), pass, countof(pass), &flags, &port))
+	{
+		connection = WinHttpConnect(this->session, host, port, 0);
+		if (connection)
+		{
+			request = WinHttpOpenRequest(connection, method, path, this->version,
+										 WINHTTP_NO_REFERER,
+										 WINHTTP_DEFAULT_ACCEPT_TYPES, flags);
+			if (request)
+			{
+				if (set_credentials(this, request, user, pass) &&
+					send_request(this, request) &&
+					read_result(this, request, userdata))
+				{
+					status = SUCCESS;
+				}
+				WinHttpCloseHandle(request);
+			}
+			else
+			{
+				DBG1(DBG_LIB, "opening request failed: %u", GetLastError());
+			}
+			WinHttpCloseHandle(connection);
+		}
+		else
+		{
+			DBG1(DBG_LIB, "connection failed: %u", GetLastError());
+		}
+	}
+	return status;
+}
+
+/**
+ * Append an header as wide string
+ */
+static bool append_header(private_winhttp_fetcher_t *this, char *name)
+{
+	int len;
+	LPWSTR buf;
+
+	len = MultiByteToWideChar(CP_THREAD_ACP, 0, name, -1, NULL, 0);
+	if (!len)
+	{
+		return FALSE;
+	}
+	buf = calloc(len, sizeof(WCHAR));
+	if (!MultiByteToWideChar(CP_THREAD_ACP, 0, name, -1, buf, len))
+	{
+		free(buf);
+		return FALSE;
+	}
+	this->headers->insert_last(this->headers, buf);
+	return TRUE;
+}
+
+METHOD(fetcher_t, set_option, bool,
+	private_winhttp_fetcher_t *this, fetcher_option_t option, ...)
+{
+	bool supported = TRUE;
+	char buf[128];
+	va_list args;
+
+	va_start(args, option);
+	switch (option)
+	{
+		case FETCH_REQUEST_DATA:
+			this->request = va_arg(args, chunk_t);
+			break;
+		case FETCH_REQUEST_TYPE:
+			snprintf(buf, sizeof(buf), "Content-Type: %s", va_arg(args, char*));
+			supported = append_header(this, buf);
+			break;
+		case FETCH_REQUEST_HEADER:
+			supported = append_header(this, va_arg(args, char*));
+			break;
+		case FETCH_HTTP_VERSION_1_0:
+			this->version = L"HTTP/1.0";
+			break;
+		case FETCH_TIMEOUT:
+			this->timeout = va_arg(args, u_int) * 1000;
+			break;
+		case FETCH_CALLBACK:
+			this->cb = va_arg(args, fetcher_callback_t);
+			break;
+		case FETCH_RESPONSE_CODE:
+			this->result = va_arg(args, u_int*);
+			break;
+		case FETCH_SOURCEIP:
+			/* not supported, FALL */
+		default:
+			supported = FALSE;
+			break;
+	}
+	va_end(args);
+	return supported;
+}
+
+METHOD(fetcher_t, destroy, void,
+	private_winhttp_fetcher_t *this)
+{
+	WinHttpCloseHandle(this->session);
+	this->headers->destroy_function(this->headers, free);
+	free(this);
+}
+/*
+ * Described in header.
+ */
+winhttp_fetcher_t *winhttp_fetcher_create()
+{
+	private_winhttp_fetcher_t *this;
+
+	INIT(this,
+		.public = {
+			.interface = {
+				.fetch = _fetch,
+				.set_option = _set_option,
+				.destroy = _destroy,
+			},
+		},
+		.version = L"HTTP/1.1",
+		.cb = fetcher_default_callback,
+		.headers = linked_list_create(),
+		.session = WinHttpOpen(L"strongSwan WinHTTP fetcher",
+							WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
+							WINHTTP_NO_PROXY_NAME,
+							WINHTTP_NO_PROXY_BYPASS, 0),
+	);
+
+	if (!this->session)
+	{
+		free(this);
+		return NULL;
+	}
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/plugins/winhttp/winhttp_fetcher.h b/src/libstrongswan/plugins/winhttp/winhttp_fetcher.h
new file mode 100644
index 0000000..6129eb8
--- /dev/null
+++ b/src/libstrongswan/plugins/winhttp/winhttp_fetcher.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup winhttp_fetcher winhttp_fetcher
+ * @{ @ingroup winhttp_p
+ */
+
+#ifndef WINHTTP_FETCHER_H_
+#define WINHTTP_FETCHER_H_
+
+#include <library.h>
+
+typedef struct winhttp_fetcher_t winhttp_fetcher_t;
+
+/**
+ * Fetcher implementation using Microsofts WinHTTP.
+ */
+struct winhttp_fetcher_t {
+
+	/**
+	 * Implements fetcher interface.
+	 */
+	fetcher_t interface;
+};
+
+/**
+ * Create a winhttp_fetcher instance
+ *
+ * @return		WinHTTP based fetcher
+ */
+winhttp_fetcher_t *winhttp_fetcher_create();
+
+#endif /** WINHTTP_FETCHER_H_ @}*/
diff --git a/src/libstrongswan/plugins/winhttp/winhttp_plugin.c b/src/libstrongswan/plugins/winhttp/winhttp_plugin.c
new file mode 100644
index 0000000..8b67ff5
--- /dev/null
+++ b/src/libstrongswan/plugins/winhttp/winhttp_plugin.c
@@ -0,0 +1,74 @@
+/*
+ * 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 "winhttp_plugin.h"
+#include "winhttp_fetcher.h"
+
+typedef struct private_winhttp_plugin_t private_winhttp_plugin_t;
+
+/**
+ * Private data of winhttp_plugin
+ */
+struct private_winhttp_plugin_t {
+
+	/**
+	 * Public functions
+	 */
+	winhttp_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_winhttp_plugin_t *this)
+{
+	return "winhttp";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_winhttp_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_REGISTER(FETCHER, winhttp_fetcher_create),
+			PLUGIN_PROVIDE(FETCHER, "http://"),
+			PLUGIN_PROVIDE(FETCHER, "https://"),
+	};
+	*features = f;
+	return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+	private_winhttp_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *winhttp_plugin_create()
+{
+	private_winhttp_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/libstrongswan/plugins/winhttp/winhttp_plugin.h b/src/libstrongswan/plugins/winhttp/winhttp_plugin.h
new file mode 100644
index 0000000..30cd051
--- /dev/null
+++ b/src/libstrongswan/plugins/winhttp/winhttp_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup winhttp_p winhttp
+ * @ingroup plugins
+ *
+ * @defgroup winhttp_plugin winhttp_plugin
+ * @{ @ingroup winhttp_p
+ */
+
+#ifndef WINHTTP_PLUGIN_H_
+#define WINHTTP_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct winhttp_plugin_t winhttp_plugin_t;
+
+/**
+ * Plugin implementing fetcher interface using Microsofts WinHTTP.
+ */
+struct winhttp_plugin_t {
+
+	/**
+	 * Implements plugin interface.
+	 */
+	plugin_t plugin;
+};
+
+#endif /** WINHTTP_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/x509/Makefile.am b/src/libstrongswan/plugins/x509/Makefile.am
index b464d14..a4160bb 100644
--- a/src/libstrongswan/plugins/x509/Makefile.am
+++ b/src/libstrongswan/plugins/x509/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-x509.la
diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in
index 154fc5c..02f2b2b 100644
--- a/src/libstrongswan/plugins/x509/Makefile.in
+++ b/src/libstrongswan/plugins/x509/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-x509.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-x509.la
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c
index 30b871d..ed58377 100644
--- a/src/libstrongswan/plugins/x509/x509_ac.c
+++ b/src/libstrongswan/plugins/x509/x509_ac.c
@@ -754,17 +754,22 @@ static chunk_t build_attr_cert_info(private_x509_ac_t *this)
 /**
  * build an X.509 attribute certificate
  */
-static chunk_t build_ac(private_x509_ac_t *this)
+static bool build_ac(private_x509_ac_t *this)
 {
 	chunk_t signatureValue, attributeCertificateInfo;
 
 	attributeCertificateInfo = build_attr_cert_info(this);
-	this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1,
-						  attributeCertificateInfo, &signatureValue);
-	return asn1_wrap(ASN1_SEQUENCE, "mmm",
-				attributeCertificateInfo,
-				asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
-				asn1_bitstring("m", signatureValue));
+	if (!this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1,
+							   attributeCertificateInfo, &signatureValue))
+	{
+		free(attributeCertificateInfo.ptr);
+		return FALSE;
+	}
+	this->encoding = asn1_wrap(ASN1_SEQUENCE, "mmm",
+						attributeCertificateInfo,
+						asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
+						asn1_bitstring("m", signatureValue));
+	return TRUE;
 }
 
 METHOD(ac_t, get_serial, chunk_t,
@@ -1154,8 +1159,10 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
 		ac->holderCert->get_type(ac->holderCert) == CERT_X509 &&
 		ac->signerCert->get_type(ac->signerCert) == CERT_X509)
 	{
-		ac->encoding = build_ac(ac);
-		return &ac->public;
+		if (build_ac(ac))
+		{
+			return &ac->public;
+		}
 	}
 	destroy(ac);
 	return NULL;
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index 9fd869e..bdc8234 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -217,10 +217,6 @@ struct private_x509_cert_t {
 	refcount_t ref;
 };
 
-static const chunk_t ASN1_subjectAltName_oid = chunk_from_chars(
-	0x06, 0x03, 0x55, 0x1D, 0x11
-);
-
 /**
  * Destroy a CertificateDistributionPoint
  */
@@ -2611,4 +2607,3 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args)
 	destroy(cert);
 	return NULL;
 }
-
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
index 1f89299..ad04c7d 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
@@ -35,6 +35,11 @@
  */
 #define OCSP_DEFAULT_LIFETIME 30
 
+/* defined in wincrypt.h */
+#ifdef OCSP_RESPONSE
+# undef OCSP_RESPONSE
+#endif
+
 typedef struct private_x509_ocsp_response_t private_x509_ocsp_response_t;
 
 /**
@@ -129,25 +134,6 @@ typedef struct {
 /* our OCSP response version implementation */
 #define OCSP_BASIC_RESPONSE_VERSION 1
 
-/* some OCSP specific prefabricated ASN.1 constants */
-static const chunk_t ASN1_nonce_oid = chunk_from_chars(
-	0x06, 0x09,
-		  0x2B, 0x06,
-				0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
-);
-static const chunk_t ASN1_response_oid = chunk_from_chars(
-	0x06, 0x09,
-		  0x2B, 0x06,
-				0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
-);
-static const chunk_t ASN1_response_content = chunk_from_chars(
-	0x04, 0x0D,
-		  0x30, 0x0B,
-				0x06, 0x09,
-				0x2B, 0x06,
-				0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
-);
-
 METHOD(ocsp_response_t, get_status, cert_validation_t,
 	private_x509_ocsp_response_t *this, x509_t *subject, x509_t *issuer,
 	time_t *revocation_time, crl_reason_t *revocation_reason,
@@ -889,4 +875,3 @@ x509_ocsp_response_t *x509_ocsp_response_load(certificate_type_t type,
 	}
 	return NULL;
 }
-
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.am b/src/libstrongswan/plugins/xcbc/Makefile.am
index 6e22272..43371cd 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.am
+++ b/src/libstrongswan/plugins/xcbc/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-xcbc.la
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.in b/src/libstrongswan/plugins/xcbc/Makefile.in
index ca61643..3c3fa07 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.in
+++ b/src/libstrongswan/plugins/xcbc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -263,6 +263,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ 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@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -413,7 +417,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libstrongswan
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-xcbc.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-xcbc.la
diff --git a/src/libstrongswan/processing/processor.c b/src/libstrongswan/processing/processor.c
index 012b169..27e5ab5 100644
--- a/src/libstrongswan/processing/processor.c
+++ b/src/libstrongswan/processing/processor.c
@@ -467,6 +467,8 @@ METHOD(processor_t, cancel, void,
 {
 	enumerator_t *enumerator;
 	worker_thread_t *worker;
+	job_t *job;
+	int i;
 
 	this->mutex->lock(this->mutex);
 	this->desired_threads = 0;
@@ -496,6 +498,14 @@ METHOD(processor_t, cancel, void,
 		worker->thread->join(worker->thread);
 		free(worker);
 	}
+	for (i = 0; i < JOB_PRIO_MAX; i++)
+	{
+		while (this->jobs[i]->remove_first(this->jobs[i],
+										   (void**)&job) == SUCCESS)
+		{
+			job->destroy(job);
+		}
+	}
 	this->mutex->unlock(this->mutex);
 }
 
@@ -510,7 +520,7 @@ METHOD(processor_t, destroy, void,
 	this->mutex->destroy(this->mutex);
 	for (i = 0; i < JOB_PRIO_MAX; i++)
 	{
-		this->jobs[i]->destroy_offset(this->jobs[i], offsetof(job_t, destroy));
+		this->jobs[i]->destroy(this->jobs[i]);
 	}
 	this->threads->destroy(this->threads);
 	free(this);
diff --git a/src/libstrongswan/processing/watcher.c b/src/libstrongswan/processing/watcher.c
index cc3c3a7..3518dfd 100644
--- a/src/libstrongswan/processing/watcher.c
+++ b/src/libstrongswan/processing/watcher.c
@@ -24,7 +24,9 @@
 
 #include <unistd.h>
 #include <errno.h>
+#ifndef WIN32
 #include <sys/select.h>
+#endif
 #include <fcntl.h>
 
 typedef struct private_watcher_t private_watcher_t;
@@ -50,6 +52,11 @@ struct private_watcher_t {
 	bool pending;
 
 	/**
+	 * Is watcher running?
+	 */
+	bool running;
+
+	/**
 	 * Lock to access FD list
 	 */
 	mutex_t *mutex;
@@ -114,7 +121,14 @@ static void update(private_watcher_t *this)
 	this->pending = TRUE;
 	if (this->notify[1] != -1)
 	{
-		ignore_result(write(this->notify[1], buf, sizeof(buf)));
+#ifdef WIN32
+		if (send(this->notify[1], buf, sizeof(buf), 0) == -1)
+#else
+		if (write(this->notify[1], buf, sizeof(buf)) == -1)
+#endif
+		{
+			DBG1(DBG_JOB, "notifying watcher failed: %s", strerror(errno));
+		}
 	}
 }
 
@@ -225,6 +239,7 @@ static void activate_all(private_watcher_t *this)
 		entry->in_callback = 0;
 	}
 	enumerator->destroy(enumerator);
+	this->running = FALSE;
 	this->condvar->broadcast(this->condvar);
 	this->mutex->unlock(this->mutex);
 }
@@ -238,14 +253,17 @@ static job_requeue_t watch(private_watcher_t *this)
 	entry_t *entry;
 	fd_set rd, wr, ex;
 	int maxfd = 0, res;
+	bool rebuild = FALSE;
 
 	FD_ZERO(&rd);
 	FD_ZERO(&wr);
 	FD_ZERO(&ex);
 
 	this->mutex->lock(this->mutex);
+
 	if (this->fds->get_count(this->fds) == 0)
 	{
+		this->running = FALSE;
 		this->mutex->unlock(this->mutex);
 		return JOB_REQUEUE_NONE;
 	}
@@ -282,25 +300,44 @@ static job_requeue_t watch(private_watcher_t *this)
 	enumerator->destroy(enumerator);
 	this->mutex->unlock(this->mutex);
 
-	while (TRUE)
+	while (!rebuild)
 	{
 		char buf[1];
 		bool old;
+		ssize_t len;
 		job_t *job;
 
 		DBG2(DBG_JOB, "watcher going to select()");
 		thread_cleanup_push((void*)activate_all, this);
 		old = thread_cancelability(TRUE);
+
 		res = select(maxfd + 1, &rd, &wr, &ex, NULL);
 		thread_cancelability(old);
 		thread_cleanup_pop(FALSE);
+
 		if (res > 0)
 		{
 			if (this->notify[0] != -1 && FD_ISSET(this->notify[0], &rd))
 			{
-				DBG2(DBG_JOB, "watcher got notification, rebuilding");
-				while (read(this->notify[0], buf, sizeof(buf)) > 0);
+				while (TRUE)
+				{
+#ifdef WIN32
+					len = recv(this->notify[0], buf, sizeof(buf), 0);
+#else
+					len = read(this->notify[0], buf, sizeof(buf));
+#endif
+					if (len == -1)
+					{
+						if (errno != EAGAIN && errno != EWOULDBLOCK)
+						{
+							DBG1(DBG_JOB, "reading watcher notify failed: %s",
+								 strerror(errno));
+						}
+						break;
+					}
+				}
 				this->pending = FALSE;
+				DBG2(DBG_JOB, "watcher got notification, rebuilding");
 				return JOB_REQUEUE_DIRECT;
 			}
 
@@ -308,6 +345,11 @@ static job_requeue_t watch(private_watcher_t *this)
 			enumerator = this->fds->create_enumerator(this->fds);
 			while (enumerator->enumerate(enumerator, &entry))
 			{
+				if (entry->in_callback)
+				{
+					rebuild = TRUE;
+					break;
+				}
 				if (FD_ISSET(entry->fd, &rd) && (entry->events & WATCHER_READ))
 				{
 					DBG2(DBG_JOB, "watched FD %d ready to read", entry->fd);
@@ -347,6 +389,7 @@ static job_requeue_t watch(private_watcher_t *this)
 			return JOB_REQUEUE_DIRECT;
 		}
 	}
+	return JOB_REQUEUE_DIRECT;
 }
 
 METHOD(watcher_t, add, void,
@@ -364,8 +407,9 @@ METHOD(watcher_t, add, void,
 
 	this->mutex->lock(this->mutex);
 	this->fds->insert_last(this->fds, entry);
-	if (this->fds->get_count(this->fds) == 1)
+	if (!this->running)
 	{
+		this->running = TRUE;
 		lib->processor->queue_job(lib->processor,
 			(job_t*)callback_job_create_with_prio((void*)watch, this,
 				NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
@@ -393,7 +437,7 @@ METHOD(watcher_t, remove_, void,
 		{
 			if (entry->fd == fd)
 			{
-				if (entry->in_callback)
+				if (this->running && entry->in_callback)
 				{
 					is_in_callback = TRUE;
 					break;
@@ -432,13 +476,60 @@ METHOD(watcher_t, destroy, void,
 	free(this);
 }
 
+#ifdef WIN32
+
+/**
+ * Create notify pipe with a TCP socketpair
+ */
+static bool create_notify(private_watcher_t *this)
+{
+	u_long on = 1;
+
+	if (socketpair(AF_INET, SOCK_STREAM, 0, this->notify) == 0)
+	{
+		/* use non-blocking I/O on read-end of notify pipe */
+		if (ioctlsocket(this->notify[0], FIONBIO, &on) == 0)
+		{
+			return TRUE;
+		}
+		DBG1(DBG_LIB, "setting watcher notify pipe read-end non-blocking "
+			 "failed: %s", strerror(errno));
+	}
+	return FALSE;
+}
+
+#else /* !WIN32 */
+
+/**
+ * Create a notify pipe with a one-directional pipe
+ */
+static bool create_notify(private_watcher_t *this)
+{
+	int flags;
+
+	if (pipe(this->notify) == 0)
+	{
+		/* use non-blocking I/O on read-end of notify pipe */
+		flags = fcntl(this->notify[0], F_GETFL);
+		if (flags != -1 &&
+			fcntl(this->notify[0], F_SETFL, flags | O_NONBLOCK) != -1)
+		{
+			return TRUE;
+		}
+		DBG1(DBG_LIB, "setting watcher notify pipe read-end non-blocking "
+			 "failed: %s", strerror(errno));
+	}
+	return FALSE;
+}
+
+#endif /* !WIN32 */
+
 /**
  * See header
  */
 watcher_t *watcher_create()
 {
 	private_watcher_t *this;
-	int flags;
 
 	INIT(this,
 		.public = {
@@ -453,18 +544,7 @@ watcher_t *watcher_create()
 		.notify = {-1, -1},
 	);
 
-	if (pipe(this->notify) == 0)
-	{
-		/* use non-blocking I/O on read-end of notify pipe */
-		flags = fcntl(this->notify[0], F_GETFL);
-		if (flags == -1 ||
-			fcntl(this->notify[0], F_SETFL, flags | O_NONBLOCK) == -1)
-		{
-			DBG1(DBG_LIB, "setting watcher notify pipe read-end non-blocking "
-				 "failed: %s", strerror(errno));
-		}
-	}
-	else
+	if (!create_notify(this))
 	{
 		DBG1(DBG_LIB, "creating watcher notify pipe failed: %s",
 			 strerror(errno));
diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c
index b9d9b65..94b7746 100644
--- a/src/libstrongswan/selectors/traffic_selector.c
+++ b/src/libstrongswan/selectors/traffic_selector.c
@@ -15,16 +15,15 @@
  * for more details.
  */
 
-#include <arpa/inet.h>
 #include <string.h>
-#include <netdb.h>
 #include <stdio.h>
 
 #include "traffic_selector.h"
 
-#include <collections/linked_list.h>
-#include <utils/identification.h>
 #include <utils/debug.h>
+#include <utils/utils.h>
+#include <utils/identification.h>
+#include <collections/linked_list.h>
 
 #define NON_SUBNET_ADDRESS_RANGE	255
 
diff --git a/src/libstrongswan/settings/settings.c b/src/libstrongswan/settings/settings.c
new file mode 100644
index 0000000..e235e3c
--- /dev/null
+++ b/src/libstrongswan/settings/settings.c
@@ -0,0 +1,944 @@
+/*
+ * Copyright (C) 2010-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "settings.h"
+#include "settings_types.h"
+
+#include "collections/array.h"
+#include "collections/hashtable.h"
+#include "collections/linked_list.h"
+#include "threading/rwlock.h"
+#include "utils/debug.h"
+
+typedef struct private_settings_t private_settings_t;
+
+/**
+ * Parse function provided by the generated parser.
+ */
+bool settings_parser_parse_file(section_t *root, char *name);
+
+/**
+ * Private data of settings
+ */
+struct private_settings_t {
+
+	/**
+	 * Public interface
+	 */
+	settings_t public;
+
+	/**
+	 * Top level section
+	 */
+	section_t *top;
+
+	/**
+	 * Contents of replaced settings (char*)
+	 *
+	 * FIXME: This is required because the pointer returned by get_str()
+	 * is not refcounted.  Might cause ever increasing usage stats.
+	 */
+	array_t *contents;
+
+	/**
+	 * Lock to safely access the settings
+	 */
+	rwlock_t *lock;
+};
+
+/**
+ * Print a format key, but consume already processed arguments
+ */
+static bool print_key(char *buf, int len, char *start, char *key, va_list args)
+{
+	va_list copy;
+	char *pos = start;
+	bool res;
+
+	va_copy(copy, args);
+	while (TRUE)
+	{
+		pos = memchr(pos, '%', key - pos);
+		if (!pos)
+		{
+			break;
+		}
+		pos++;
+		switch (*pos)
+		{
+			case 'd':
+				va_arg(copy, int);
+				break;
+			case 's':
+				va_arg(copy, char*);
+				break;
+			case 'N':
+				va_arg(copy, enum_name_t*);
+				va_arg(copy, int);
+				break;
+			case '%':
+				break;
+			default:
+				DBG1(DBG_CFG, "settings with %%%c not supported!", *pos);
+				break;
+		}
+		pos++;
+	}
+	res = vsnprintf(buf, len, key, copy) < len;
+	va_end(copy);
+	return res;
+}
+
+/**
+ * Find a section by a given key, using buffered key, reusable buffer.
+ * If "ensure" is TRUE, the sections are created if they don't exist.
+ */
+static section_t *find_section_buffered(section_t *section,
+					char *start, char *key, va_list args, char *buf, int len,
+					bool ensure)
+{
+	char *pos;
+	section_t *found = NULL;
+
+	if (section == NULL)
+	{
+		return NULL;
+	}
+	pos = strchr(key, '.');
+	if (pos)
+	{
+		*pos = '\0';
+		pos++;
+	}
+	if (!print_key(buf, len, start, key, args))
+	{
+		return NULL;
+	}
+	if (!strlen(buf))
+	{
+		found = section;
+	}
+	else if (array_bsearch(section->sections, buf, settings_section_find,
+						   &found) == -1)
+	{
+		if (ensure)
+		{
+			found = settings_section_create(strdup(buf));
+			settings_section_add(section, found, NULL);
+		}
+	}
+	if (found && pos)
+	{
+		return find_section_buffered(found, start, pos, args, buf, len, ensure);
+	}
+	return found;
+}
+
+/**
+ * Find all sections via a given key considering fallbacks, using buffered key,
+ * reusable buffer.
+ */
+static void find_sections_buffered(section_t *section, char *start, char *key,
+						va_list args, char *buf, int len, array_t **sections)
+{
+	section_t *found = NULL, *fallback;
+	char *pos;
+	int i;
+
+	if (!section)
+	{
+		return;
+	}
+	pos = strchr(key, '.');
+	if (pos)
+	{
+		*pos = '\0';
+	}
+	if (!print_key(buf, len, start, key, args))
+	{
+		return;
+	}
+	if (pos)
+	{	/* restore so we can follow fallbacks */
+		*pos = '.';
+	}
+	if (!strlen(buf))
+	{
+		found = section;
+	}
+	else
+	{
+		array_bsearch(section->sections, buf, settings_section_find, &found);
+	}
+	if (found)
+	{
+		if (pos)
+		{
+			find_sections_buffered(found, start, pos+1, args, buf, len,
+								   sections);
+		}
+		else
+		{
+			array_insert_create(sections, ARRAY_TAIL, found);
+			for (i = 0; i < array_count(found->fallbacks); i++)
+			{
+				array_get(found->fallbacks, i, &fallback);
+				array_insert_create(sections, ARRAY_TAIL, fallback);
+			}
+		}
+	}
+	if (section->fallbacks)
+	{
+		for (i = 0; i < array_count(section->fallbacks); i++)
+		{
+			array_get(section->fallbacks, i, &fallback);
+			find_sections_buffered(fallback, start, key, args, buf, len,
+								   sections);
+		}
+	}
+}
+
+/**
+ * Ensure that the section with the given key exists (thread-safe).
+ */
+static section_t *ensure_section(private_settings_t *this, section_t *section,
+								 const char *key, va_list args)
+{
+	char buf[128], keybuf[512];
+	section_t *found;
+
+	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+	{
+		return NULL;
+	}
+	/* we might have to change the tree */
+	this->lock->write_lock(this->lock);
+	found = find_section_buffered(section, keybuf, keybuf, args, buf,
+								  sizeof(buf), TRUE);
+	this->lock->unlock(this->lock);
+	return found;
+}
+
+/**
+ * Find a section by a given key with its fallbacks (not thread-safe!).
+ * Sections are returned in depth-first order (array is allocated). NULL is
+ * returned if no sections are found.
+ */
+static array_t *find_sections(private_settings_t *this, section_t *section,
+							  char *key, va_list args)
+{
+	char buf[128], keybuf[512];
+	array_t *sections = NULL;
+
+	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+	{
+		return NULL;
+	}
+	find_sections_buffered(section, keybuf, keybuf, args, buf,
+						   sizeof(buf), &sections);
+	return sections;
+}
+
+/**
+ * Check if the given fallback section already exists
+ */
+static bool fallback_exists(section_t *section, section_t *fallback)
+{
+	if (section == fallback)
+	{
+		return TRUE;
+	}
+	else if (section->fallbacks)
+	{
+		section_t *existing;
+		int i;
+
+		for (i = 0; i < array_count(section->fallbacks); i++)
+		{
+			array_get(section->fallbacks, i, &existing);
+			if (existing == fallback)
+			{
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Ensure that the section with the given key exists and add the given fallback
+ * section (thread-safe).
+ */
+static void add_fallback_to_section(private_settings_t *this,
+							section_t *section, const char *key, va_list args,
+							section_t *fallback)
+{
+	char buf[128], keybuf[512];
+	section_t *found;
+
+	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+	{
+		return;
+	}
+	this->lock->write_lock(this->lock);
+	found = find_section_buffered(section, keybuf, keybuf, args, buf,
+								  sizeof(buf), TRUE);
+	if (!fallback_exists(found, fallback))
+	{
+		/* to ensure sections referred to as fallback are not purged, we create
+		 * the array there too */
+		if (!fallback->fallbacks)
+		{
+			fallback->fallbacks = array_create(0, 0);
+		}
+		array_insert_create(&found->fallbacks, ARRAY_TAIL, fallback);
+	}
+	this->lock->unlock(this->lock);
+}
+
+/**
+ * Find the key/value pair for a key, using buffered key, reusable buffer
+ * If "ensure" is TRUE, the sections (and key/value pair) are created if they
+ * don't exist.
+ * Fallbacks are only considered if "ensure" is FALSE.
+ */
+static kv_t *find_value_buffered(section_t *section, char *start, char *key,
+								 va_list args, char *buf, int len, bool ensure)
+{
+	int i;
+	char *pos;
+	kv_t *kv = NULL;
+	section_t *found = NULL;
+
+	if (section == NULL)
+	{
+		return NULL;
+	}
+
+	pos = strchr(key, '.');
+	if (pos)
+	{
+		*pos = '\0';
+		if (!print_key(buf, len, start, key, args))
+		{
+			return NULL;
+		}
+		/* restore so we can retry for fallbacks */
+		*pos = '.';
+		if (!strlen(buf))
+		{
+			found = section;
+		}
+		else if (array_bsearch(section->sections, buf, settings_section_find,
+							   &found) == -1)
+		{
+			if (ensure)
+			{
+				found = settings_section_create(strdup(buf));
+				settings_section_add(section, found, NULL);
+			}
+		}
+		if (found)
+		{
+			kv = find_value_buffered(found, start, pos+1, args, buf, len,
+									 ensure);
+		}
+		if (!kv && !ensure && section->fallbacks)
+		{
+			for (i = 0; !kv && i < array_count(section->fallbacks); i++)
+			{
+				array_get(section->fallbacks, i, &found);
+				kv = find_value_buffered(found, start, key, args, buf, len,
+										 ensure);
+			}
+		}
+	}
+	else
+	{
+		if (!print_key(buf, len, start, key, args))
+		{
+			return NULL;
+		}
+		if (array_bsearch(section->kv, buf, settings_kv_find, &kv) == -1)
+		{
+			if (ensure)
+			{
+				kv = settings_kv_create(strdup(buf), NULL);
+				settings_kv_add(section, kv, NULL);
+			}
+			else if (section->fallbacks)
+			{
+				for (i = 0; !kv && i < array_count(section->fallbacks); i++)
+				{
+					array_get(section->fallbacks, i, &found);
+					kv = find_value_buffered(found, start, key, args, buf, len,
+											 ensure);
+				}
+			}
+		}
+	}
+	return kv;
+}
+
+/**
+ * Find the string value for a key (thread-safe).
+ */
+static char *find_value(private_settings_t *this, section_t *section,
+						char *key, va_list args)
+{
+	char buf[128], keybuf[512], *value = NULL;
+	kv_t *kv;
+
+	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+	{
+		return NULL;
+	}
+	this->lock->read_lock(this->lock);
+	kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
+							 FALSE);
+	if (kv)
+	{
+		value = kv->value;
+	}
+	this->lock->unlock(this->lock);
+	return value;
+}
+
+/**
+ * Set a value to a copy of the given string (thread-safe).
+ */
+static void set_value(private_settings_t *this, section_t *section,
+					  char *key, va_list args, char *value)
+{
+	char buf[128], keybuf[512];
+	kv_t *kv;
+
+	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+	{
+		return;
+	}
+	this->lock->write_lock(this->lock);
+	kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
+							 TRUE);
+	if (kv)
+	{
+		settings_kv_set(kv, strdupnull(value), this->contents);
+	}
+	this->lock->unlock(this->lock);
+}
+
+METHOD(settings_t, get_str, char*,
+	private_settings_t *this, char *key, char *def, ...)
+{
+	char *value;
+	va_list args;
+
+	va_start(args, def);
+	value = find_value(this, this->top, key, args);
+	va_end(args);
+	if (value)
+	{
+		return value;
+	}
+	return def;
+}
+
+/**
+ * Described in header
+ */
+inline bool settings_value_as_bool(char *value, bool def)
+{
+	if (value)
+	{
+		if (strcaseeq(value, "1") ||
+			strcaseeq(value, "yes") ||
+			strcaseeq(value, "true") ||
+			strcaseeq(value, "enabled"))
+		{
+			return TRUE;
+		}
+		else if (strcaseeq(value, "0") ||
+				 strcaseeq(value, "no") ||
+				 strcaseeq(value, "false") ||
+				 strcaseeq(value, "disabled"))
+		{
+			return FALSE;
+		}
+	}
+	return def;
+}
+
+METHOD(settings_t, get_bool, bool,
+	private_settings_t *this, char *key, bool def, ...)
+{
+	char *value;
+	va_list args;
+
+	va_start(args, def);
+	value = find_value(this, this->top, key, args);
+	va_end(args);
+	return settings_value_as_bool(value, def);
+}
+
+/**
+ * Described in header
+ */
+inline int settings_value_as_int(char *value, int def)
+{
+	int intval;
+	char *end;
+
+	if (value)
+	{
+		errno = 0;
+		intval = strtol(value, &end, 10);
+		if (errno == 0 && *end == 0 && end != value)
+		{
+			return intval;
+		}
+	}
+	return def;
+}
+
+METHOD(settings_t, get_int, int,
+	private_settings_t *this, char *key, int def, ...)
+{
+	char *value;
+	va_list args;
+
+	va_start(args, def);
+	value = find_value(this, this->top, key, args);
+	va_end(args);
+	return settings_value_as_int(value, def);
+}
+
+/**
+ * Described in header
+ */
+inline double settings_value_as_double(char *value, double def)
+{
+	double dval;
+	char *end;
+
+	if (value)
+	{
+		errno = 0;
+		dval = strtod(value, &end);
+		if (errno == 0 && *end == 0 && end != value)
+		{
+			return dval;
+		}
+	}
+	return def;
+}
+
+METHOD(settings_t, get_double, double,
+	private_settings_t *this, char *key, double def, ...)
+{
+	char *value;
+	va_list args;
+
+	va_start(args, def);
+	value = find_value(this, this->top, key, args);
+	va_end(args);
+	return settings_value_as_double(value, def);
+}
+
+/**
+ * Described in header
+ */
+inline u_int32_t settings_value_as_time(char *value, u_int32_t def)
+{
+	char *endptr;
+	u_int32_t timeval;
+	if (value)
+	{
+		errno = 0;
+		timeval = strtoul(value, &endptr, 10);
+		if (endptr == value)
+		{
+			return def;
+		}
+		if (errno == 0)
+		{
+			while (isspace(*endptr))
+			{
+				endptr++;
+			}
+			switch (*endptr)
+			{
+				case 'd':		/* time in days */
+					timeval *= 24 * 3600;
+					break;
+				case 'h':		/* time in hours */
+					timeval *= 3600;
+					break;
+				case 'm':		/* time in minutes */
+					timeval *= 60;
+					break;
+				case 's':		/* time in seconds */
+				case '\0':
+					break;
+				default:
+					return def;
+			}
+			return timeval;
+		}
+	}
+	return def;
+}
+
+METHOD(settings_t, get_time, u_int32_t,
+	private_settings_t *this, char *key, u_int32_t def, ...)
+{
+	char *value;
+	va_list args;
+
+	va_start(args, def);
+	value = find_value(this, this->top, key, args);
+	va_end(args);
+	return settings_value_as_time(value, def);
+}
+
+METHOD(settings_t, set_str, void,
+	private_settings_t *this, char *key, char *value, ...)
+{
+	va_list args;
+	va_start(args, value);
+	set_value(this, this->top, key, args, value);
+	va_end(args);
+}
+
+METHOD(settings_t, set_bool, void,
+	private_settings_t *this, char *key, bool value, ...)
+{
+	va_list args;
+	va_start(args, value);
+	set_value(this, this->top, key, args, value ? "1" : "0");
+	va_end(args);
+}
+
+METHOD(settings_t, set_int, void,
+	private_settings_t *this, char *key, int value, ...)
+{
+	char val[16];
+	va_list args;
+	va_start(args, value);
+	if (snprintf(val, sizeof(val), "%d", value) < sizeof(val))
+	{
+		set_value(this, this->top, key, args, val);
+	}
+	va_end(args);
+}
+
+METHOD(settings_t, set_double, void,
+	private_settings_t *this, char *key, double value, ...)
+{
+	char val[64];
+	va_list args;
+	va_start(args, value);
+	if (snprintf(val, sizeof(val), "%f", value) < sizeof(val))
+	{
+		set_value(this, this->top, key, args, val);
+	}
+	va_end(args);
+}
+
+METHOD(settings_t, set_time, void,
+	private_settings_t *this, char *key, u_int32_t value, ...)
+{
+	char val[16];
+	va_list args;
+	va_start(args, value);
+	if (snprintf(val, sizeof(val), "%u", value) < sizeof(val))
+	{
+		set_value(this, this->top, key, args, val);
+	}
+	va_end(args);
+}
+
+METHOD(settings_t, set_default_str, bool,
+	private_settings_t *this, char *key, char *value, ...)
+{
+	char *old;
+	va_list args;
+
+	va_start(args, value);
+	old = find_value(this, this->top, key, args);
+	va_end(args);
+
+	if (!old)
+	{
+		va_start(args, value);
+		set_value(this, this->top, key, args, value);
+		va_end(args);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Data for enumerators
+ */
+typedef struct {
+	/** settings_t instance */
+	private_settings_t *settings;
+	/** sections to enumerate */
+	array_t *sections;
+	/** sections/keys that were already enumerated */
+	hashtable_t *seen;
+} enumerator_data_t;
+
+/**
+ * Destroy enumerator data
+ */
+static void enumerator_destroy(enumerator_data_t *this)
+{
+	this->settings->lock->unlock(this->settings->lock);
+	this->seen->destroy(this->seen);
+	array_destroy(this->sections);
+	free(this);
+}
+
+/**
+ * Enumerate section names, not sections
+ */
+static bool section_filter(hashtable_t *seen, section_t **in, char **out)
+{
+	*out = (*in)->name;
+	if (seen->get(seen, *out))
+	{
+		return FALSE;
+	}
+	seen->put(seen, *out, *out);
+	return TRUE;
+}
+
+/**
+ * Enumerate sections of the given section
+ */
+static enumerator_t *section_enumerator(section_t *section,
+										enumerator_data_t *data)
+{
+	return enumerator_create_filter(
+			array_create_enumerator(section->sections_order),
+				(void*)section_filter, data->seen, NULL);
+}
+
+METHOD(settings_t, create_section_enumerator, enumerator_t*,
+	private_settings_t *this, char *key, ...)
+{
+	enumerator_data_t *data;
+	array_t *sections;
+	va_list args;
+
+	this->lock->read_lock(this->lock);
+	va_start(args, key);
+	sections = find_sections(this, this->top, key, args);
+	va_end(args);
+
+	if (!sections)
+	{
+		this->lock->unlock(this->lock);
+		return enumerator_create_empty();
+	}
+	INIT(data,
+		.settings = this,
+		.sections = sections,
+		.seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
+	);
+	return enumerator_create_nested(array_create_enumerator(sections),
+					(void*)section_enumerator, data, (void*)enumerator_destroy);
+}
+
+/**
+ * Enumerate key and values, not kv_t entries
+ */
+static bool kv_filter(hashtable_t *seen, kv_t **in, char **key,
+					  void *none, char **value)
+{
+	*key = (*in)->key;
+	if (seen->get(seen, *key) || !(*in)->value)
+	{
+		return FALSE;
+	}
+	*value = (*in)->value;
+	seen->put(seen, *key, *key);
+	return TRUE;
+}
+
+/**
+ * Enumerate key/value pairs of the given section
+ */
+static enumerator_t *kv_enumerator(section_t *section, enumerator_data_t *data)
+{
+	return enumerator_create_filter(array_create_enumerator(section->kv_order),
+					(void*)kv_filter, data->seen, NULL);
+}
+
+METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
+	private_settings_t *this, char *key, ...)
+{
+	enumerator_data_t *data;
+	array_t *sections;
+	va_list args;
+
+	this->lock->read_lock(this->lock);
+	va_start(args, key);
+	sections = find_sections(this, this->top, key, args);
+	va_end(args);
+
+	if (!sections)
+	{
+		this->lock->unlock(this->lock);
+		return enumerator_create_empty();
+	}
+	INIT(data,
+		.settings = this,
+		.sections = sections,
+		.seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
+	);
+	return enumerator_create_nested(array_create_enumerator(sections),
+					(void*)kv_enumerator, data, (void*)enumerator_destroy);
+}
+
+METHOD(settings_t, add_fallback, void,
+	private_settings_t *this, const char *key, const char *fallback, ...)
+{
+	section_t *section;
+	va_list args;
+
+	/* find/create the fallback */
+	va_start(args, fallback);
+	section = ensure_section(this, this->top, fallback, args);
+	va_end(args);
+
+	va_start(args, fallback);
+	add_fallback_to_section(this, this->top, key, args, section);
+	va_end(args);
+}
+
+/**
+ * Load settings from files matching the given file pattern.
+ * All sections and values are added relative to "parent".
+ * All files (even included ones) have to be loaded successfully.
+ * If merge is FALSE the contents of parent are replaced with the parsed
+ * contents, otherwise they are merged together.
+ */
+static bool load_files_internal(private_settings_t *this, section_t *parent,
+								char *pattern, bool merge)
+{
+	section_t *section;
+
+	if (pattern == NULL || !pattern[0])
+	{	/* TODO: Clear parent if merge is FALSE? */
+		return FALSE;
+	}
+
+	section = settings_section_create(NULL);
+	if (!settings_parser_parse_file(section, pattern))
+	{
+		settings_section_destroy(section, NULL);
+		return FALSE;
+	}
+
+	this->lock->write_lock(this->lock);
+	settings_section_extend(parent, section, this->contents, !merge);
+	this->lock->unlock(this->lock);
+
+	settings_section_destroy(section, NULL);
+	return TRUE;
+}
+
+METHOD(settings_t, load_files, bool,
+	private_settings_t *this, char *pattern, bool merge)
+{
+	return load_files_internal(this, this->top, pattern, merge);
+}
+
+METHOD(settings_t, load_files_section, bool,
+	private_settings_t *this, char *pattern, bool merge, char *key, ...)
+{
+	section_t *section;
+	va_list args;
+
+	va_start(args, key);
+	section = ensure_section(this, this->top, key, args);
+	va_end(args);
+
+	if (!section)
+	{
+		return FALSE;
+	}
+	return load_files_internal(this, section, pattern, merge);
+}
+
+METHOD(settings_t, destroy, void,
+	private_settings_t *this)
+{
+	settings_section_destroy(this->top, NULL);
+	array_destroy_function(this->contents, (void*)free, NULL);
+	this->lock->destroy(this->lock);
+	free(this);
+}
+
+/*
+ * see header file
+ */
+settings_t *settings_create(char *file)
+{
+	private_settings_t *this;
+
+	INIT(this,
+		.public = {
+			.get_str = _get_str,
+			.get_int = _get_int,
+			.get_double = _get_double,
+			.get_time = _get_time,
+			.get_bool = _get_bool,
+			.set_str = _set_str,
+			.set_int = _set_int,
+			.set_double = _set_double,
+			.set_time = _set_time,
+			.set_bool = _set_bool,
+			.set_default_str = _set_default_str,
+			.create_section_enumerator = _create_section_enumerator,
+			.create_key_value_enumerator = _create_key_value_enumerator,
+			.add_fallback = _add_fallback,
+			.load_files = _load_files,
+			.load_files_section = _load_files_section,
+			.destroy = _destroy,
+		},
+		.top = settings_section_create(NULL),
+		.contents = array_create(0, 0),
+		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+	);
+
+	load_files(this, file, FALSE);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/settings/settings.h b/src/libstrongswan/settings/settings.h
new file mode 100644
index 0000000..3b87c8f
--- /dev/null
+++ b/src/libstrongswan/settings/settings.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup settings settings
+ * @ingroup libstrongswan
+ *
+ * @defgroup settings_t settings
+ * @{ @ingroup settings
+ */
+
+#ifndef SETTINGS_H_
+#define SETTINGS_H_
+
+typedef struct settings_t settings_t;
+
+#include "utils/utils.h"
+#include "collections/enumerator.h"
+
+/**
+ * Convert a string value returned by a key/value enumerator to a boolean.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_bool()
+ * @param value			the string value
+ * @param def			the default value, if value is NULL or invalid
+ */
+bool settings_value_as_bool(char *value, bool def);
+
+/**
+ * Convert a string value returned by a key/value enumerator to an integer.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_int()
+ * @param value			the string value
+ * @param def			the default value, if value is NULL or invalid
+ */
+int settings_value_as_int(char *value, int def);
+
+/**
+ * Convert a string value returned by a key/value enumerator to a double.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_double()
+ * @param value			the string value
+ * @param def			the default value, if value is NULL or invalid
+ */
+double settings_value_as_double(char *value, double def);
+
+/**
+ * Convert a string value returned by a key/value enumerator to a time value.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_time()
+ * @param value			the string value
+ * @param def			the default value, if value is NULL or invalid
+ */
+u_int32_t settings_value_as_time(char *value, u_int32_t def);
+
+/**
+ * Generic configuration options read from a config file.
+ *
+ * The syntax is quite simple:
+ * @code
+ * settings := (section|keyvalue)*
+ * section  := name { settings }
+ * keyvalue := key = value\n
+ * @endcode
+ * E.g.:
+ * @code
+	a = b
+	section-one {
+		somevalue = asdf
+		subsection {
+			othervalue = xxx
+		}
+		yetanother = zz
+	}
+	section-two {
+	}
+	@endcode
+ *
+ * The values are accessed using the get() functions using dotted keys, e.g.
+ *   section-one.subsection.othervalue
+ *
+ * Currently only a limited set of printf format specifiers are supported
+ * (namely %s, %d and %N, see implementation for details).
+ *
+ * \section includes Including other files
+ * Other files can be included, using the include statement e.g.
+ * @code
+ *   include /somepath/subconfig.conf
+ * @endcode
+ * Shell patterns like *.conf are possible.
+ *
+ * If the path is relative, the directory of the file containing the include
+ * statement is used as base.
+ *
+ * Sections loaded from included files extend previously loaded sections,
+ * already existing values are replaced.
+ *
+ * All settings included from files are added relative to the section the
+ * include statement is in.
+ *
+ * The following files result in the same final config as above:
+ *
+ * @code
+	a = b
+	section-one {
+		somevalue = before include
+		include include.conf
+	}
+	include two.conf
+	@endcode
+ * include.conf
+ * @code
+	somevalue = asdf
+	subsection {
+		othervalue = yyy
+	}
+	yetanother = zz
+	@endcode
+ * two.conf
+ * @code
+	section-one {
+		subsection {
+			othervalue = xxx
+		}
+	}
+	section-two {
+	}
+	@endcode
+ */
+struct settings_t {
+
+	/**
+	 * Get a settings value as a string.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param def		value returned if key not found
+	 * @param ...		argument list for key
+	 * @return			value pointing to internal string
+	 */
+	char* (*get_str)(settings_t *this, char *key, char *def, ...);
+
+	/**
+	 * Get a boolean yes|no, true|false value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param def		value returned if key not found
+	 * @param ...		argument list for key
+	 * @return			value of the key
+	 */
+	bool (*get_bool)(settings_t *this, char *key, bool def, ...);
+
+	/**
+	 * Get an integer value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param def		value returned if key not found
+	 * @param ...		argument list for key
+	 * @return			value of the key
+	 */
+	int (*get_int)(settings_t *this, char *key, int def, ...);
+
+	/**
+	 * Get an double value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param def		value returned if key not found
+	 * @param ...		argument list for key
+	 * @return			value of the key
+	 */
+	double (*get_double)(settings_t *this, char *key, double def, ...);
+
+	/**
+	 * Get a time value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param def		value returned if key not found
+	 * @param ...		argument list for key
+	 * @return			value of the key (in seconds)
+	 */
+	u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...);
+
+	/**
+	 * Set a string value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param value		value to set (gets cloned)
+	 * @param ...		argument list for key
+	 */
+	void (*set_str)(settings_t *this, char *key, char *value, ...);
+
+	/**
+	 * Set a boolean value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param value		value to set
+	 * @param ...		argument list for key
+	 */
+	void (*set_bool)(settings_t *this, char *key, bool value, ...);
+
+	/**
+	 * Set an integer value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param value		value to set
+	 * @param ...		argument list for key
+	 */
+	void (*set_int)(settings_t *this, char *key, int value, ...);
+
+	/**
+	 * Set an double value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param value		value to set
+	 * @param ...		argument list for key
+	 */
+	void (*set_double)(settings_t *this, char *key, double value, ...);
+
+	/**
+	 * Set a time value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param def		value to set
+	 * @param ...		argument list for key
+	 */
+	void (*set_time)(settings_t *this, char *key, u_int32_t value, ...);
+
+	/**
+	 * Set a default for string value.
+	 *
+	 * @param key		key including sections, printf style format
+	 * @param def		value to set if unconfigured
+	 * @param ...		argument list for key
+	 * @return			TRUE if a new default value for key has been set
+	 */
+	bool (*set_default_str)(settings_t *this, char *key, char *value, ...);
+
+	/**
+	 * Create an enumerator over subsection names of a section.
+	 *
+	 * @param section	section including parents, printf style format
+	 * @param ...		argument list for key
+	 * @return			enumerator over subsection names
+	 */
+	enumerator_t* (*create_section_enumerator)(settings_t *this,
+											   char *section, ...);
+
+	/**
+	 * Create an enumerator over key/value pairs in a section.
+	 *
+	 * @param section	section name to list key/value pairs of, printf style
+	 * @param ...		argument list for section
+	 * @return			enumerator over (char *key, char *value)
+	 */
+	enumerator_t* (*create_key_value_enumerator)(settings_t *this,
+												 char *section, ...);
+
+	/**
+	 * Add a fallback for the given section.
+	 *
+	 * Example: When the fallback 'section-two' is configured for
+	 * 'section-one.two' any failed lookup for a section or key in
+	 * 'section-one.two' will result in a lookup for the same section/key
+	 * in 'section-two'.
+	 *
+	 * @note Lookups are depth-first and currently strictly top-down.
+	 * For instance, if app.sec had lib1.sec as fallback and lib1 had lib2 as
+	 * fallback the keys/sections in lib2.sec would not be considered.  But if
+	 * app had lib3 as fallback the contents of lib3.sec would (as app is passed
+	 * during the initial lookup).  In the last example the order during
+	 * enumerations would be app.sec, lib1.sec, lib3.sec.
+	 *
+	 * @note Additional arguments will be applied to both section format
+	 * strings so they must be compatible.
+	 *
+	 * @param section	section for which a fallback is configured, printf style
+	 * @param fallback	fallback section, printf style
+	 * @param ...		argument list for section and fallback
+	 */
+	void (*add_fallback)(settings_t *this, const char *section,
+						 const char *fallback, ...);
+
+	/**
+	 * Load settings from the files matching the given pattern.
+	 *
+	 * If merge is TRUE, existing sections are extended, existing values
+	 * replaced, by those found in the loaded files. If it is FALSE, existing
+	 * sections are purged before reading the new config.
+	 *
+	 * @note If any of the files matching the pattern fails to load, no settings
+	 * are added at all. So, it's all or nothing.
+	 *
+	 * @param pattern	file pattern
+	 * @param merge		TRUE to merge config with existing values
+	 * @return			TRUE, if settings were loaded successfully
+	 */
+	bool (*load_files)(settings_t *this, char *pattern, bool merge);
+
+	/**
+	 * Load settings from the files matching the given pattern.
+	 *
+	 * If merge is TRUE, existing sections are extended, existing values
+	 * replaced, by those found in the loaded files. If it is FALSE, existing
+	 * sections are purged before reading the new config.
+	 *
+	 * All settings are loaded relative to the given section. The section is
+	 * created, if it does not yet exist.
+	 *
+	 * @note If any of the files matching the pattern fails to load, no settings
+	 * are added at all. So, it's all or nothing.
+	 *
+	 * @param pattern	file pattern
+	 * @param merge		TRUE to merge config with existing values
+	 * @param section	section name of parent section, printf style
+	 * @param ...		argument list for section
+	 * @return			TRUE, if settings were loaded successfully
+	 */
+	bool (*load_files_section)(settings_t *this, char *pattern, bool merge,
+							   char *section, ...);
+
+	/**
+	 * Destroy a settings instance.
+	 */
+	void (*destroy)(settings_t *this);
+};
+
+/**
+ * Load settings from a file.
+ *
+ * @note If parsing the file fails the object is still created.
+ *
+ * @param file			optional file to read settings from
+ * @return				settings object
+ */
+settings_t *settings_create(char *file);
+
+#endif /** SETTINGS_H_ @}*/
diff --git a/src/libstrongswan/settings/settings_lexer.c b/src/libstrongswan/settings/settings_lexer.c
new file mode 100644
index 0000000..7643301
--- /dev/null
+++ b/src/libstrongswan/settings/settings_lexer.c
@@ -0,0 +1,2686 @@
+#line 2 "settings/settings_lexer.c"
+
+#line 4 "settings/settings_lexer.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+/* %not-for-header */
+
+/* %if-c-only */
+/* %if-not-reentrant */
+/* %endif */
+/* %endif */
+/* %ok-for-header */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* %if-c++-only */
+/* %endif */
+
+/* %if-c-only */
+    
+/* %endif */
+
+/* %if-c-only */
+
+/* %endif */
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+/* %if-c-only */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+/* %endif */
+
+/* %if-tables-serialization */
+/* %endif */
+/* end standard C headers. */
+
+/* %if-c-or-c++ */
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* %endif */
+
+/* %if-c++-only */
+/* %endif */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* %not-for-header */
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+/* %ok-for-header */
+
+/* %not-for-header */
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+/* %ok-for-header */
+
+/* %if-reentrant */
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* %endif */
+
+/* %if-not-reentrant */
+/* %endif */
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE settings_parser_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+/* %if-not-reentrant */
+/* %endif */
+
+/* %if-c-only */
+/* %if-not-reentrant */
+/* %endif */
+/* %endif */
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE settings_parser_lex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+/* %if-c-only */
+	FILE *yy_input_file;
+/* %endif */
+
+/* %if-c++-only */
+/* %endif */
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via settings_parser_restart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
+
+/* %if-not-reentrant */
+/* %endif */
+/* %ok-for-header */
+
+/* %endif */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+/* %if-c-only Standard (non-C++) definition */
+
+/* %if-not-reentrant */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
+
+void settings_parser_restart (FILE *input_file ,yyscan_t yyscanner );
+void settings_parser__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE settings_parser__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void settings_parser__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void settings_parser__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void settings_parser_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void settings_parser_pop_buffer_state (yyscan_t yyscanner );
+
+static void settings_parser_ensure_buffer_stack (yyscan_t yyscanner );
+static void settings_parser__load_buffer_state (yyscan_t yyscanner );
+static void settings_parser__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER settings_parser__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE settings_parser__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE settings_parser__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE settings_parser__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+/* %endif */
+
+void *settings_parser_alloc (yy_size_t ,yyscan_t yyscanner );
+void *settings_parser_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void settings_parser_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer settings_parser__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        settings_parser_ensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        settings_parser_ensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
+/* Begin user sect3 */
+
+#define settings_parser_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+#define FLEX_DEBUG
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+/* %if-c-only Standard (non-C++) definition */
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* %endif */
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
+	yyg->yy_c_buf_p = yy_cp;
+
+/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
+#define YY_NUM_RULES 25
+#define YY_END_OF_BUFFER 26
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[50] =
+    {   0,
+        0,    0,    0,    0,    0,    0,   26,    9,    2,    3,
+        8,    1,    6,    9,    4,    5,   14,   10,   11,   12,
+       24,   16,   15,   17,    9,    2,    1,    1,    3,    9,
+       14,   13,   24,   23,   21,   22,   18,   19,   20,    1,
+        9,    9,    9,    9,    9,    0,    7,    7,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    4,    1,    5,    6,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        7,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    8,    1,    1,    1,    1,    1,    9,   10,   11,
+
+       12,   13,    1,    1,   14,    1,    1,   15,    1,   16,
+        1,    1,    1,   17,    1,   18,   19,    1,    1,    1,
+        1,    1,   20,    1,   21,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[22] =
+    {   0,
+        1,    2,    3,    4,    5,    4,    6,    7,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    8,
+        4
+    } ;
+
+static yyconst flex_int16_t yy_base[60] =
+    {   0,
+        0,    0,   20,   40,   24,   28,   63,    0,   33,  145,
+      145,   57,  145,   43,  145,  145,    0,  145,  145,    0,
+        0,  145,  145,   53,    0,   45,    0,   55,  145,   47,
+        0,  145,    0,  145,  145,  145,  145,  145,  145,    0,
+       41,   35,   23,   18,   36,   48,  145,   51,  145,   71,
+       79,   87,   94,  102,  107,  112,  120,  128,  136
+    } ;
+
+static yyconst flex_int16_t yy_def[60] =
+    {   0,
+       49,    1,   50,   50,   51,   51,   49,   52,   49,   49,
+       49,   53,   49,   52,   49,   49,   54,   49,   49,   55,
+       56,   49,   49,   57,   52,   49,   58,   53,   49,   52,
+       54,   49,   56,   49,   49,   49,   49,   49,   49,   58,
+       52,   52,   52,   52,   52,   59,   49,   59,    0,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49
+    } ;
+
+static yyconst flex_int16_t yy_nxt[167] =
+    {   0,
+        8,    9,   10,    9,   11,   12,   13,    8,    8,    8,
+        8,    8,    8,   14,    8,    8,    8,    8,    8,   15,
+       16,   18,   18,   18,   19,   18,   22,   20,   23,   45,
+       22,   24,   23,   44,   26,   24,   26,   46,   27,   46,
+       18,   18,   18,   18,   19,   18,   26,   20,   26,   48,
+       27,   48,   48,   43,   48,   42,   41,   29,   30,   29,
+       18,   35,   49,   49,   49,   36,   49,   49,   37,   38,
+       39,   17,   17,   17,   17,   17,   17,   17,   17,   21,
+       21,   21,   21,   21,   21,   21,   21,   25,   49,   49,
+       49,   49,   49,   25,   28,   28,   28,   28,   28,   28,
+
+       28,   28,   31,   49,   49,   49,   49,   31,   49,   31,
+       32,   32,   33,   33,   49,   33,   49,   33,   49,   33,
+       34,   34,   34,   34,   34,   34,   34,   34,   40,   40,
+       49,   40,   40,   40,   40,   40,   47,   47,   47,   47,
+       47,   49,   47,   47,    7,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49
+    } ;
+
+static yyconst flex_int16_t yy_chk[167] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    3,    3,    3,    3,    3,    5,    3,    5,   44,
+        6,    5,    6,   43,    9,    6,    9,   45,    9,   45,
+        3,    4,    4,    4,    4,    4,   26,    4,   26,   46,
+       26,   46,   48,   42,   48,   41,   30,   28,   14,   12,
+        4,   24,    7,    0,    0,   24,    0,    0,   24,   24,
+       24,   50,   50,   50,   50,   50,   50,   50,   50,   51,
+       51,   51,   51,   51,   51,   51,   51,   52,    0,    0,
+        0,    0,    0,   52,   53,   53,   53,   53,   53,   53,
+
+       53,   53,   54,    0,    0,    0,    0,   54,    0,   54,
+       55,   55,   56,   56,    0,   56,    0,   56,    0,   56,
+       57,   57,   57,   57,   57,   57,   57,   57,   58,   58,
+        0,   58,   58,   58,   58,   58,   59,   59,   59,   59,
+       59,    0,   59,   59,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49,   49,   49,   49,   49,
+       49,   49,   49,   49,   49,   49
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[26] =
+    {   0,
+0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 
+    0, 0, 0, 1, 0, 0,     };
+
+static yyconst flex_int16_t yy_rule_linenum[25] =
+    {   0,
+       59,   60,   61,   63,   64,   65,   67,   72,   77,   85,
+      105,  108,  111,  114,  120,  122,  123,  146,  147,  148,
+      149,  150,  151,  154
+    } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "settings/settings_lexer.l"
+#line 2 "settings/settings_lexer.l"
+/*
+ * 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 <utils/parser_helper.h>
+
+#include "settings_parser.h"
+
+bool settings_parser_open_next_file(parser_helper_t *ctx);
+
+static void include_files(parser_helper_t *ctx);
+
+/* use start conditions stack */
+/* do not declare unneded functions */
+#define YY_NO_INPUT 1
+/* don't use global variables, and interact properly with bison */
+/* maintain the line number */
+/* don't generate a default rule */
+/* prefix function/variable declarations */
+/* don't change the name of the output file otherwise autotools has issues */
+/* type of our extra data */
+/* state used to scan include file patterns */
+
+/* state used to scan quoted strings */
+
+#line 639 "settings/settings_lexer.c"
+
+#define INITIAL 0
+#define inc 1
+#define str 2
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+/* %if-c-only */
+#include <unistd.h>
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+#endif
+
+#define YY_EXTRA_TYPE parser_helper_t*
+
+/* %if-c-only Reentrant structure and macros (non-C++). */
+/* %if-reentrant */
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    }; /* end struct yyguts_t */
+
+/* %if-c-only */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+/* %endif */
+
+/* %if-reentrant */
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+int settings_parser_lex_init (yyscan_t* scanner);
+
+int settings_parser_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* %endif */
+
+/* %endif End reentrant structures and macros. */
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int settings_parser_lex_destroy (yyscan_t yyscanner );
+
+int settings_parser_get_debug (yyscan_t yyscanner );
+
+void settings_parser_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE settings_parser_get_extra (yyscan_t yyscanner );
+
+void settings_parser_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *settings_parser_get_in (yyscan_t yyscanner );
+
+void settings_parser_set_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *settings_parser_get_out (yyscan_t yyscanner );
+
+void settings_parser_set_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int settings_parser_get_leng (yyscan_t yyscanner );
+
+char *settings_parser_get_text (yyscan_t yyscanner );
+
+int settings_parser_get_lineno (yyscan_t yyscanner );
+
+void settings_parser_set_lineno (int line_number ,yyscan_t yyscanner );
+
+/* %if-bison-bridge */
+
+YYSTYPE * settings_parser_get_lval (yyscan_t yyscanner );
+
+void settings_parser_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* %endif */
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int settings_parser_wrap (yyscan_t yyscanner );
+#else
+extern int settings_parser_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+/* %not-for-header */
+
+    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
+    
+/* %ok-for-header */
+
+/* %endif */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+/* %ok-for-header */
+
+/* %endif */
+#endif
+
+/* %if-c-only */
+
+    static void yy_push_state (int new_state ,yyscan_t yyscanner);
+    
+    static void yy_pop_state (yyscan_t yyscanner );
+    
+    static int yy_top_state (yyscan_t yyscanner );
+    
+/* %endif */
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* %if-c-only Standard (non-C++) definition */
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+/* %endif */
+/* %if-c++-only C++ definition */
+/* %endif */
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+/* %if-c++-only C++ definition \ */\
+/* %endif */
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+/* %if-c-only */
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+#endif
+
+/* %if-tables-serialization structures and prototypes */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %not-for-header */
+
+/* %tables-yydmap generated elements */
+/* %endif */
+/* end tables serialization structures and prototypes */
+
+/* %ok-for-header */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+/* %if-c-only Standard (non-C++) definition */
+
+extern int settings_parser_lex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int settings_parser_lex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only C++ definition */
+/* %endif */
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+/* %% [6.0] YY_RULE_SETUP definition goes here */
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/* %not-for-header */
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+/* %% [7.0] user's declarations go here */
+#line 57 "settings/settings_lexer.l"
+
+
+#line 951 "settings/settings_lexer.c"
+
+    yylval = yylval_param;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+/* %if-c-only */
+			yyin = stdin;
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+		if ( ! yyout )
+/* %if-c-only */
+			yyout = stdout;
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			settings_parser_ensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		settings_parser__load_buffer_state(yyscanner );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+/* %% [8.0] yymore()-related code goes here */
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+/* %% [9.0] code to set up and find next match goes here */
+		yy_current_state = yyg->yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 50 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 145 );
+
+yy_find_action:
+/* %% [10.0] code to find the action number goes here */
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+/* %% [11.0] code for yylineno update goes here */
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+/* %% [12.0] debug code goes here */
+		if ( yy_flex_debug )
+			{
+			if ( yy_act == 0 )
+				fprintf( stderr, "--scanner backing up\n" );
+			else if ( yy_act < 25 )
+				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
+				         (long)yy_rule_linenum[yy_act], yytext );
+			else if ( yy_act == 25 )
+				fprintf( stderr, "--accepting default rule (\"%s\")\n",
+				         yytext );
+			else if ( yy_act == 26 )
+				fprintf( stderr, "--(end of buffer or a NUL)\n" );
+			else
+				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
+			}
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+/* %% [13.0] actions go here */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 59 "settings/settings_lexer.l"
+/* eat comments */
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 60 "settings/settings_lexer.l"
+/* eat whitespace */
+	YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 61 "settings/settings_lexer.l"
+return NEWLINE; /* also eats comments at the end of a line */
+	YY_BREAK
+case 4:
+#line 64 "settings/settings_lexer.l"
+case 5:
+#line 65 "settings/settings_lexer.l"
+case 6:
+YY_RULE_SETUP
+#line 65 "settings/settings_lexer.l"
+return yytext[0];
+	YY_BREAK
+case 7:
+/* rule 7 can match eol */
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 67 "settings/settings_lexer.l"
+{
+	yyextra->string_init(yyextra);
+	yy_push_state(inc, yyscanner);
+}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 72 "settings/settings_lexer.l"
+{
+	yyextra->string_init(yyextra);
+	yy_push_state(str, yyscanner);
+}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 77 "settings/settings_lexer.l"
+{
+	yylval->s = strdup(yytext);
+	return NAME;
+}
+	YY_BREAK
+
+/* we allow all characters except #, } and spaces, they can be escaped */
+case YY_STATE_EOF(inc):
+#line 84 "settings/settings_lexer.l"
+case 10:
+/* rule 10 can match eol */
+YY_RULE_SETUP
+#line 85 "settings/settings_lexer.l"
+{
+		if (*yytext)
+		{
+			switch (yytext[0])
+			{
+				case '\n':
+					/* put the newline back to fix the line numbers */
+					unput('\n');
+					yy_set_bol(0);
+					break;
+				case '#':
+				case '}':
+					/* these are parsed outside of this start condition */
+					unput(yytext[0]);
+					break;
+			}
+		}
+		include_files(yyextra);
+		yy_pop_state(yyscanner);
+	}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 105 "settings/settings_lexer.l"
+{	/* string include */
+		yy_push_state(str, yyscanner);
+	}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 108 "settings/settings_lexer.l"
+{
+		yyextra->string_add(yyextra, yytext);
+	}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 111 "settings/settings_lexer.l"
+{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 114 "settings/settings_lexer.l"
+{
+		yyextra->string_add(yyextra, yytext);
+	}
+	YY_BREAK
+
+
+case 15:
+#line 121 "settings/settings_lexer.l"
+case YY_STATE_EOF(str):
+#line 121 "settings/settings_lexer.l"
+case 16:
+/* rule 16 can match eol */
+#line 123 "settings/settings_lexer.l"
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 123 "settings/settings_lexer.l"
+{
+		if (!streq(yytext, "\""))
+		{
+			if (streq(yytext, "\n"))
+			{	/* put the newline back to fix the line numbers */
+				unput('\n');
+				yy_set_bol(0);
+			}
+			PARSER_DBG1(yyextra, "unterminated string detected");
+		}
+		if (yy_top_state(yyscanner) == inc)
+		{	/* string include */
+			include_files(yyextra);
+			yy_pop_state(yyscanner);
+			yy_pop_state(yyscanner);
+		}
+		else
+		{
+			yy_pop_state(yyscanner);
+			yylval->s = yyextra->string_get(yyextra);
+			return STRING;
+		}
+	}
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 146 "settings/settings_lexer.l"
+yyextra->string_add(yyextra, "\n");
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 147 "settings/settings_lexer.l"
+yyextra->string_add(yyextra, "\r");
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 148 "settings/settings_lexer.l"
+yyextra->string_add(yyextra, "\t");
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 149 "settings/settings_lexer.l"
+yyextra->string_add(yyextra, "\b");
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 150 "settings/settings_lexer.l"
+yyextra->string_add(yyextra, "\f");
+	YY_BREAK
+case 23:
+/* rule 23 can match eol */
+YY_RULE_SETUP
+#line 151 "settings/settings_lexer.l"
+{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 154 "settings/settings_lexer.l"
+{
+		yyextra->string_add(yyextra, yytext);
+	}
+	YY_BREAK
+
+case YY_STATE_EOF(INITIAL):
+#line 159 "settings/settings_lexer.l"
+{
+	settings_parser_pop_buffer_state(yyscanner);
+	if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
+	{
+		yyterminate();
+	}
+}
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 167 "settings/settings_lexer.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+	YY_BREAK
+#line 1282 "settings/settings_lexer.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * settings_parser_lex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */
+				yy_cp = yyg->yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( settings_parser_wrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of settings_parser_lex */
+/* %ok-for-header */
+
+/* %if-c++-only */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+/* %if-c-only */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = yyg->yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					settings_parser_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			yyg->yy_n_chars, (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			settings_parser_restart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) settings_parser_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+/* %if-c-only */
+/* %not-for-header */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+/* %% [15.0] code to get the start state into yy_current_state goes here */
+	yy_current_state = yyg->yy_start;
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+/* %% [16.0] code to find the next state goes here */
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 50 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+/* %if-c-only */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+/* %% [17.0] code to find the next state, and perhaps do backing up, goes here */
+	register char *yy_cp = yyg->yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 50 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 49);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+/* %if-c-only */
+
+    static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yy_cp = yyg->yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yyg->yy_hold_char;
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yyg->yy_n_chars + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+/* %% [18.0] update yylineno here */
+
+    if ( c == '\n' ){
+        --yylineno;
+    }
+
+	yyg->yytext_ptr = yy_bp;
+	yyg->yy_hold_char = *yy_cp;
+	yyg->yy_c_buf_p = yy_cp;
+}
+/* %if-c-only */
+
+/* %endif */
+
+/* %if-c-only */
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					settings_parser_restart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( settings_parser_wrap(yyscanner ) )
+						return EOF;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+/* %% [19.0] update BOL and yylineno */
+	if ( c == '\n' )
+		   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+/* %if-c-only */
+#endif	/* ifndef YY_NO_INPUT */
+/* %endif */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+/* %if-c-only */
+    void settings_parser_restart  (FILE * input_file , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        settings_parser_ensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            settings_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	settings_parser__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	settings_parser__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+    void settings_parser__switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		settings_parser_pop_buffer_state();
+	 *		settings_parser_push_buffer_state(new_buffer);
+     */
+	settings_parser_ensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	settings_parser__load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (settings_parser_wrap()) processing, but the only time this flag
+	 * is looked at is after settings_parser_wrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/* %if-c-only */
+static void settings_parser__load_buffer_state  (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+/* %if-c-only */
+    YY_BUFFER_STATE settings_parser__create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) settings_parser_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in settings_parser__create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) settings_parser_alloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in settings_parser__create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	settings_parser__init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with settings_parser__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+    void settings_parser__delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		settings_parser_free((void *) b->yy_ch_buf ,yyscanner );
+
+	settings_parser_free((void *) b ,yyscanner );
+}
+
+/* %if-c-only */
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* %endif */
+
+/* %if-c++-only */
+/* %endif */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a settings_parser_restart() or at EOF.
+ */
+/* %if-c-only */
+    static void settings_parser__init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	settings_parser__flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then settings_parser__init_buffer was _probably_
+     * called from settings_parser_restart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+/* %if-c-only */
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+    void settings_parser__flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		settings_parser__load_buffer_state(yyscanner );
+}
+
+/* %if-c-or-c++ */
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+void settings_parser_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	settings_parser_ensure_buffer_stack(yyscanner);
+
+	/* This block is copied from settings_parser__switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from settings_parser__switch_to_buffer. */
+	settings_parser__load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+void settings_parser_pop_buffer_state (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	settings_parser__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		settings_parser__load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+/* %if-c-only */
+static void settings_parser_ensure_buffer_stack (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)settings_parser_alloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in settings_parser_ensure_buffer_stack()" );
+								  
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)settings_parser_realloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in settings_parser_ensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE settings_parser__scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) settings_parser_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in settings_parser__scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	settings_parser__switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan a string. The next call to settings_parser_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       settings_parser__scan_bytes() instead.
+ */
+YY_BUFFER_STATE settings_parser__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+	return settings_parser__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan the given bytes. The next call to settings_parser_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE settings_parser__scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) settings_parser_alloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in settings_parser__scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = settings_parser__scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in settings_parser__scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+/* %endif */
+
+/* %if-c-only */
+    static void yy_push_state (int  new_state , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yyg->yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yyg->yy_start_stack_depth * sizeof( int );
+
+		if ( ! yyg->yy_start_stack )
+			yyg->yy_start_stack = (int *) settings_parser_alloc(new_size ,yyscanner );
+
+		else
+			yyg->yy_start_stack = (int *) settings_parser_realloc((void *) yyg->yy_start_stack,new_size ,yyscanner );
+
+		if ( ! yyg->yy_start_stack )
+			YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+		}
+
+	yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+}
+
+/* %if-c-only */
+    static void yy_pop_state  (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( --yyg->yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]);
+}
+
+/* %if-c-only */
+    static int yy_top_state  (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+/* %if-c-only */
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/* %if-c-only */
+/* %if-reentrant */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE settings_parser_get_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/* %endif */
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int settings_parser_get_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int settings_parser_get_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *settings_parser_get_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *settings_parser_get_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int settings_parser_get_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *settings_parser_get_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/* %if-reentrant */
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void settings_parser_set_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/* %endif */
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void settings_parser_set_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "settings_parser_set_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void settings_parser_set_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "settings_parser_set_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see settings_parser__switch_to_buffer
+ */
+void settings_parser_set_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void settings_parser_set_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int settings_parser_get_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void settings_parser_set_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* %endif */
+
+/* %if-reentrant */
+/* Accessor methods for yylval and yylloc */
+
+/* %if-bison-bridge */
+
+YYSTYPE * settings_parser_get_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void settings_parser_set_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+/* %endif */
+
+/* User-visible API */
+
+/* settings_parser_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int settings_parser_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) settings_parser_alloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* settings_parser_lex_init_extra has the same functionality as settings_parser_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to settings_parser_alloc in
+ * the yyextra field.
+ */
+
+int settings_parser_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    settings_parser_set_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) settings_parser_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    settings_parser_set_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* %endif if-c-only */
+
+/* %if-c-only */
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from settings_parser_lex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * settings_parser_lex_init()
+     */
+    return 0;
+}
+/* %endif */
+
+/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */
+/* settings_parser_lex_destroy is for both reentrant and non-reentrant scanners. */
+int settings_parser_lex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		settings_parser__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		settings_parser_pop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	settings_parser_free(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        settings_parser_free(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * settings_parser_lex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+/* %if-reentrant */
+    /* Destroy the main struct (reentrant only). */
+    settings_parser_free ( yyscanner , yyscanner );
+    yyscanner = NULL;
+/* %endif */
+    return 0;
+}
+/* %endif */
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *settings_parser_alloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	return (void *) malloc( size );
+}
+
+void *settings_parser_realloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void settings_parser_free (void * ptr , yyscan_t yyscanner)
+{
+	free( (char *) ptr );	/* see settings_parser_realloc() for (char *) cast */
+}
+
+/* %if-tables-serialization definitions */
+/* %define-yytables   The name for this specific scanner's tables. */
+#define YYTABLES_NAME "yytables"
+/* %endif */
+
+/* %ok-for-header */
+
+#line 167 "settings/settings_lexer.l"
+
+
+
+/**
+ * Open the next file, if any is queued and readable, otherwise returns FALSE.
+ */
+bool settings_parser_open_next_file(parser_helper_t *ctx)
+{
+	FILE *file;
+
+	file = ctx->file_next(ctx);
+	if (!file)
+	{
+		return FALSE;
+	}
+
+	settings_parser_set_in(file, ctx->scanner);
+	settings_parser_push_buffer_state(
+			settings_parser__create_buffer(file, YY_BUF_SIZE,
+										   ctx->scanner), ctx->scanner);
+	return TRUE;
+}
+
+/**
+ * Assumes that the file pattern to include is currently stored as string on
+ * the helper object.
+ */
+static void include_files(parser_helper_t *ctx)
+{
+	char *pattern = ctx->string_get(ctx);
+
+	ctx->file_include(ctx, pattern);
+	free(pattern);
+
+	settings_parser_open_next_file(ctx);
+}
+
diff --git a/src/libstrongswan/settings/settings_lexer.l b/src/libstrongswan/settings/settings_lexer.l
new file mode 100644
index 0000000..c6546f4
--- /dev/null
+++ b/src/libstrongswan/settings/settings_lexer.l
@@ -0,0 +1,201 @@
+%{
+/*
+ * 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 <utils/parser_helper.h>
+
+#include "settings_parser.h"
+
+bool settings_parser_open_next_file(parser_helper_t *ctx);
+
+static void include_files(parser_helper_t *ctx);
+
+%}
+%option debug
+%option warn
+
+/* use start conditions stack */
+%option stack
+
+/* do not declare unneded functions */
+%option noinput noyywrap
+
+/* don't use global variables, and interact properly with bison */
+%option reentrant bison-bridge
+
+/* maintain the line number */
+%option yylineno
+
+/* don't generate a default rule */
+%option nodefault
+
+/* prefix function/variable declarations */
+%option prefix="settings_parser_"
+/* don't change the name of the output file otherwise autotools has issues */
+%option outfile="lex.yy.c"
+
+/* type of our extra data */
+%option extra-type="parser_helper_t*"
+
+/* state used to scan include file patterns */
+%x inc
+/* state used to scan quoted strings */
+%x str
+
+%%
+
+[\t ]*#[^\n]*			/* eat comments */
+[\t ]+					/* eat whitespace */
+\n|#.*\n				return NEWLINE; /* also eats comments at the end of a line */
+
+"{"						|
+"}"						|
+"="						return yytext[0];
+
+"include"[\t ]+/[^=]	{
+	yyextra->string_init(yyextra);
+	yy_push_state(inc, yyscanner);
+}
+
+"\""					{
+	yyextra->string_init(yyextra);
+	yy_push_state(str, yyscanner);
+}
+
+[^#{}="\n\t ]+			{
+	yylval->s = strdup(yytext);
+	return NAME;
+}
+
+<inc>{
+	/* we allow all characters except #, } and spaces, they can be escaped */
+	<<EOF>>				|
+	[#}\n\t ]			{
+		if (*yytext)
+		{
+			switch (yytext[0])
+			{
+				case '\n':
+					/* put the newline back to fix the line numbers */
+					unput('\n');
+					yy_set_bol(0);
+					break;
+				case '#':
+				case '}':
+					/* these are parsed outside of this start condition */
+					unput(yytext[0]);
+					break;
+			}
+		}
+		include_files(yyextra);
+		yy_pop_state(yyscanner);
+	}
+	"\""				{	/* string include */
+		yy_push_state(str, yyscanner);
+	}
+	\\					{
+		yyextra->string_add(yyextra, yytext);
+	}
+	\\["#} ]			{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	[^"\\#}\n\t ]+ {
+		yyextra->string_add(yyextra, yytext);
+	}
+}
+
+<str>{
+	"\""				|
+	<<EOF>>				|
+	\n					|
+	\\					{
+		if (!streq(yytext, "\""))
+		{
+			if (streq(yytext, "\n"))
+			{	/* put the newline back to fix the line numbers */
+				unput('\n');
+				yy_set_bol(0);
+			}
+			PARSER_DBG1(yyextra, "unterminated string detected");
+		}
+		if (yy_top_state(yyscanner) == inc)
+		{	/* string include */
+			include_files(yyextra);
+			yy_pop_state(yyscanner);
+			yy_pop_state(yyscanner);
+		}
+		else
+		{
+			yy_pop_state(yyscanner);
+			yylval->s = yyextra->string_get(yyextra);
+			return STRING;
+		}
+	}
+	\\n     yyextra->string_add(yyextra, "\n");
+	\\r     yyextra->string_add(yyextra, "\r");
+	\\t     yyextra->string_add(yyextra, "\t");
+	\\b     yyextra->string_add(yyextra, "\b");
+	\\f     yyextra->string_add(yyextra, "\f");
+	\\(.|\n)			{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	[^\\\n"]+			{
+		yyextra->string_add(yyextra, yytext);
+	}
+}
+
+<<EOF>>					{
+	settings_parser_pop_buffer_state(yyscanner);
+	if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
+	{
+		yyterminate();
+	}
+}
+
+%%
+
+/**
+ * Open the next file, if any is queued and readable, otherwise returns FALSE.
+ */
+bool settings_parser_open_next_file(parser_helper_t *ctx)
+{
+	FILE *file;
+
+	file = ctx->file_next(ctx);
+	if (!file)
+	{
+		return FALSE;
+	}
+
+	settings_parser_set_in(file, ctx->scanner);
+	settings_parser_push_buffer_state(
+			settings_parser__create_buffer(file, YY_BUF_SIZE,
+										   ctx->scanner), ctx->scanner);
+	return TRUE;
+}
+
+/**
+ * Assumes that the file pattern to include is currently stored as string on
+ * the helper object.
+ */
+static void include_files(parser_helper_t *ctx)
+{
+	char *pattern = ctx->string_get(ctx);
+
+	ctx->file_include(ctx, pattern);
+	free(pattern);
+
+	settings_parser_open_next_file(ctx);
+}
diff --git a/src/libstrongswan/settings/settings_parser.c b/src/libstrongswan/settings/settings_parser.c
new file mode 100644
index 0000000..23e552d
--- /dev/null
+++ b/src/libstrongswan/settings/settings_parser.c
@@ -0,0 +1,1747 @@
+/* A Bison parser, made by GNU Bison 3.0.2.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.2"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names.  */
+#define yyparse         settings_parser_parse
+#define yylex           settings_parser_lex
+#define yyerror         settings_parser_error
+#define yydebug         settings_parser_debug
+#define yynerrs         settings_parser_nerrs
+
+
+/* Copy the first part of user declarations.  */
+#line 1 "settings/settings_parser.y" /* yacc.c:339  */
+
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE /* for asprintf() */
+#include <stdio.h>
+
+#include <library.h>
+#include <collections/array.h>
+#include <settings/settings_types.h>
+#include <utils/parser_helper.h>
+
+#include "settings_parser.h"
+
+#define YYDEBUG 1
+
+/**
+ * Defined by the lexer
+ */
+int settings_parser_lex(YYSTYPE *lvalp, void *scanner);
+int settings_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
+int settings_parser_lex_destroy(void *scanner);
+int settings_parser_set_in(FILE *in, void *scanner);
+void settings_parser_set_debug(int debug, void *scanner);
+char *settings_parser_get_text(void *scanner);
+int settings_parser_get_leng(void *scanner);
+int settings_parser_get_lineno(void *scanner);
+/* Custom functions in lexer */
+bool settings_parser_open_next_file(parser_helper_t *ctx);
+
+/**
+ * Forward declarations
+ */
+static void settings_parser_error(parser_helper_t *ctx, const char *s);
+static section_t *push_section(parser_helper_t *ctx, char *name);
+static section_t *pop_section(parser_helper_t *ctx);
+static void add_section(parser_helper_t *ctx, section_t *section);
+static void add_setting(parser_helper_t *ctx, kv_t *kv);
+
+/**
+ * Make sure to call lexer with the proper context
+ */
+#undef yylex
+static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
+{
+	return settings_parser_lex(lvalp, ctx->scanner);
+}
+
+
+#line 134 "settings/settings_parser.c" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "y.tab.h".  */
+#ifndef YY_SETTINGS_PARSER_SETTINGS_SETTINGS_PARSER_H_INCLUDED
+# define YY_SETTINGS_PARSER_SETTINGS_SETTINGS_PARSER_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int settings_parser_debug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    NAME = 258,
+    STRING = 259,
+    NEWLINE = 260
+  };
+#endif
+/* Tokens.  */
+#define NAME 258
+#define STRING 259
+#define NEWLINE 260
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE YYSTYPE;
+union YYSTYPE
+{
+#line 76 "settings/settings_parser.y" /* yacc.c:355  */
+
+	char *s;
+	struct section_t *sec;
+	struct kv_t *kv;
+
+#line 190 "settings/settings_parser.c" /* yacc.c:355  */
+};
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int settings_parser_parse (parser_helper_t *ctx);
+
+#endif /* !YY_SETTINGS_PARSER_SETTINGS_SETTINGS_PARSER_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 204 "settings/settings_parser.c" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   13
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  9
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  8
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  15
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  20
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   260
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     8,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     7,     2,     6,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint8 yyrline[] =
+{
+       0,   104,   104,   106,   107,   111,   115,   122,   130,   135,
+     142,   147,   154,   155,   169,   170
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "NAME", "STRING", "NEWLINE", "'}'",
+  "'{'", "'='", "$accept", "statements", "statement", "section",
+  "section_start", "setting", "value", "valuepart", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   125,   123,    61
+};
+# endif
+
+#define YYPACT_NINF -5
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-5)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+      -5,     0,    -5,    -1,    -5,    -5,    -5,    -5,    -5,     2,
+      -5,    -2,     5,    -5,    -5,    -5,    -2,    -5,    -5,    -5
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     0,     1,     0,     3,     4,     5,     2,     6,     0,
+       8,    11,     0,     9,    14,    15,    10,    12,     7,    13
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+      -5,     6,    -5,    -5,    -5,    -5,    -5,    -4
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     1,     5,     6,     7,     8,    16,    17
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+       2,    14,    15,     3,     9,     4,    10,    11,     3,    13,
+       4,    18,    19,    12
+};
+
+static const yytype_uint8 yycheck[] =
+{
+       0,     3,     4,     3,     5,     5,     7,     8,     3,     7,
+       5,     6,    16,     7
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    10,     0,     3,     5,    11,    12,    13,    14,     5,
+       7,     8,    10,     7,     3,     4,    15,    16,     6,    16
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,     9,    10,    10,    10,    11,    11,    12,    13,    13,
+      14,    14,    15,    15,    16,    16
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     2,     1,     1,     3,     2,     3,
+       3,     2,     1,     2,     1,     1
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (ctx, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, ctx); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_helper_t *ctx)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (ctx);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_helper_t *ctx)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, ctx);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, parser_helper_t *ctx)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , ctx);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, ctx); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_helper_t *ctx)
+{
+  YYUSE (yyvaluep);
+  YYUSE (ctx);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  switch (yytype)
+    {
+          case 3: /* NAME  */
+#line 90 "settings/settings_parser.y" /* yacc.c:1257  */
+      { free(((*yyvaluep).s)); }
+#line 1028 "settings/settings_parser.c" /* yacc.c:1257  */
+        break;
+
+    case 4: /* STRING  */
+#line 90 "settings/settings_parser.y" /* yacc.c:1257  */
+      { free(((*yyvaluep).s)); }
+#line 1034 "settings/settings_parser.c" /* yacc.c:1257  */
+        break;
+
+    case 12: /* section  */
+#line 92 "settings/settings_parser.y" /* yacc.c:1257  */
+      { pop_section(ctx); settings_section_destroy(((*yyvaluep).sec), NULL); }
+#line 1040 "settings/settings_parser.c" /* yacc.c:1257  */
+        break;
+
+    case 13: /* section_start  */
+#line 92 "settings/settings_parser.y" /* yacc.c:1257  */
+      { pop_section(ctx); settings_section_destroy(((*yyvaluep).sec), NULL); }
+#line 1046 "settings/settings_parser.c" /* yacc.c:1257  */
+        break;
+
+    case 14: /* setting  */
+#line 93 "settings/settings_parser.y" /* yacc.c:1257  */
+      { settings_kv_destroy(((*yyvaluep).kv), NULL); }
+#line 1052 "settings/settings_parser.c" /* yacc.c:1257  */
+        break;
+
+    case 15: /* value  */
+#line 90 "settings/settings_parser.y" /* yacc.c:1257  */
+      { free(((*yyvaluep).s)); }
+#line 1058 "settings/settings_parser.c" /* yacc.c:1257  */
+        break;
+
+    case 16: /* valuepart  */
+#line 90 "settings/settings_parser.y" /* yacc.c:1257  */
+      { free(((*yyvaluep).s)); }
+#line 1064 "settings/settings_parser.c" /* yacc.c:1257  */
+        break;
+
+
+      default:
+        break;
+    }
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (parser_helper_t *ctx)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, ctx);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 5:
+#line 112 "settings/settings_parser.y" /* yacc.c:1646  */
+    {
+		add_section(ctx, (yyvsp[0].sec));
+	}
+#line 1334 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+  case 6:
+#line 116 "settings/settings_parser.y" /* yacc.c:1646  */
+    {
+		add_setting(ctx, (yyvsp[0].kv));
+	}
+#line 1342 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 123 "settings/settings_parser.y" /* yacc.c:1646  */
+    {
+		pop_section(ctx);
+		(yyval.sec) = (yyvsp[-2].sec);
+	}
+#line 1351 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 131 "settings/settings_parser.y" /* yacc.c:1646  */
+    {
+		(yyval.sec) = push_section(ctx, (yyvsp[-1].s));
+	}
+#line 1359 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 136 "settings/settings_parser.y" /* yacc.c:1646  */
+    {
+		(yyval.sec) = push_section(ctx, (yyvsp[-2].s));
+	}
+#line 1367 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 143 "settings/settings_parser.y" /* yacc.c:1646  */
+    {
+		(yyval.kv) = settings_kv_create((yyvsp[-2].s), (yyvsp[0].s));
+	}
+#line 1375 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 148 "settings/settings_parser.y" /* yacc.c:1646  */
+    {
+		(yyval.kv) = settings_kv_create((yyvsp[-1].s), NULL);
+	}
+#line 1383 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 156 "settings/settings_parser.y" /* yacc.c:1646  */
+    {	/* just put a single space between them, use strings for more */
+		if (asprintf(&(yyval.s), "%s %s", (yyvsp[-1].s), (yyvsp[0].s)) < 0)
+		{
+			free((yyvsp[-1].s));
+			free((yyvsp[0].s));
+			YYERROR;
+		}
+		free((yyvsp[-1].s));
+		free((yyvsp[0].s));
+	}
+#line 1398 "settings/settings_parser.c" /* yacc.c:1646  */
+    break;
+
+
+#line 1402 "settings/settings_parser.c" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (ctx, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (ctx, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, ctx);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, ctx);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (ctx, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, ctx);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, ctx);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 173 "settings/settings_parser.y" /* yacc.c:1906  */
+
+
+/**
+ * Referenced by the generated parser
+ */
+static void settings_parser_error(parser_helper_t *ctx, const char *s)
+{
+	char *text = settings_parser_get_text(ctx->scanner);
+	int len = settings_parser_get_leng(ctx->scanner);
+
+	if (len && text[len-1] == '\n')
+	{	/* cut off newline at the end to avoid muti-line log messages */
+		len--;
+	}
+	PARSER_DBG1(ctx, "%s [%.*s]", s, len, text);
+}
+
+/**
+ * Create a section and push it to the stack (the name is adopted), returns
+ * the created section
+ */
+static section_t *push_section(parser_helper_t *ctx, char *name)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *section;
+
+	section = settings_section_create(name);
+	array_insert(sections, ARRAY_TAIL, section);
+	return section;
+}
+
+/**
+ * Removes the top section of the stack and returns it
+ */
+static section_t *pop_section(parser_helper_t *ctx)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *section;
+
+	array_remove(sections, ARRAY_TAIL, &section);
+	return section;
+}
+
+/**
+ * Adds the given section to the section on top of the stack
+ */
+static void add_section(parser_helper_t *ctx, section_t *section)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *parent;
+
+	array_get(sections, ARRAY_TAIL, &parent);
+	settings_section_add(parent, section, NULL);
+}
+
+/**
+ * Adds the given key/value pair to the section on top of the stack
+ */
+static void add_setting(parser_helper_t *ctx, kv_t *kv)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *section;
+
+	array_get(sections, ARRAY_TAIL, &section);
+	settings_kv_add(section, kv, NULL);
+}
+
+/**
+ * Parse the given file and add all sections and key/value pairs to the
+ * given section.
+ */
+bool settings_parser_parse_file(section_t *root, char *name)
+{
+	parser_helper_t *helper;
+	array_t *sections = NULL;
+	bool success = FALSE;
+
+	array_insert_create(&sections, ARRAY_TAIL, root);
+	helper = parser_helper_create(sections);
+	helper->get_lineno = settings_parser_get_lineno;
+	if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
+	{
+		helper->destroy(helper);
+		array_destroy(sections);
+		return FALSE;
+	}
+	helper->file_include(helper, name);
+	if (!settings_parser_open_next_file(helper))
+	{
+#ifdef STRONGSWAN_CONF
+		if (streq(name, STRONGSWAN_CONF))
+		{
+			DBG2(DBG_CFG, "failed to open config file '%s'", name);
+		}
+		else
+#endif
+		{
+			DBG1(DBG_CFG, "failed to open config file '%s'", name);
+		}
+	}
+	else
+	{
+		if (getenv("DEBUG_SETTINGS_PARSER"))
+		{
+			yydebug = 1;
+			settings_parser_set_debug(1, helper->scanner);
+		}
+		success = yyparse(helper) == 0;
+		if (!success)
+		{
+			DBG1(DBG_CFG, "invalid config file '%s'", name);
+		}
+	}
+	array_destroy(sections);
+	settings_parser_lex_destroy(helper->scanner);
+	helper->destroy(helper);
+	return success;
+}
diff --git a/src/libstrongswan/settings/settings_parser.h b/src/libstrongswan/settings/settings_parser.h
new file mode 100644
index 0000000..9d56465
--- /dev/null
+++ b/src/libstrongswan/settings/settings_parser.h
@@ -0,0 +1,79 @@
+/* A Bison parser, made by GNU Bison 3.0.2.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_SETTINGS_PARSER_SETTINGS_SETTINGS_PARSER_H_INCLUDED
+# define YY_SETTINGS_PARSER_SETTINGS_SETTINGS_PARSER_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int settings_parser_debug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    NAME = 258,
+    STRING = 259,
+    NEWLINE = 260
+  };
+#endif
+/* Tokens.  */
+#define NAME 258
+#define STRING 259
+#define NEWLINE 260
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE YYSTYPE;
+union YYSTYPE
+{
+#line 76 "settings/settings_parser.y" /* yacc.c:1909  */
+
+	char *s;
+	struct section_t *sec;
+	struct kv_t *kv;
+
+#line 70 "settings/settings_parser.h" /* yacc.c:1909  */
+};
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int settings_parser_parse (parser_helper_t *ctx);
+
+#endif /* !YY_SETTINGS_PARSER_SETTINGS_SETTINGS_PARSER_H_INCLUDED  */
diff --git a/src/libstrongswan/settings/settings_parser.y b/src/libstrongswan/settings/settings_parser.y
new file mode 100644
index 0000000..b79faf6
--- /dev/null
+++ b/src/libstrongswan/settings/settings_parser.y
@@ -0,0 +1,290 @@
+%{
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE /* for asprintf() */
+#include <stdio.h>
+
+#include <library.h>
+#include <collections/array.h>
+#include <settings/settings_types.h>
+#include <utils/parser_helper.h>
+
+#include "settings_parser.h"
+
+#define YYDEBUG 1
+
+/**
+ * Defined by the lexer
+ */
+int settings_parser_lex(YYSTYPE *lvalp, void *scanner);
+int settings_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
+int settings_parser_lex_destroy(void *scanner);
+int settings_parser_set_in(FILE *in, void *scanner);
+void settings_parser_set_debug(int debug, void *scanner);
+char *settings_parser_get_text(void *scanner);
+int settings_parser_get_leng(void *scanner);
+int settings_parser_get_lineno(void *scanner);
+/* Custom functions in lexer */
+bool settings_parser_open_next_file(parser_helper_t *ctx);
+
+/**
+ * Forward declarations
+ */
+static void settings_parser_error(parser_helper_t *ctx, const char *s);
+static section_t *push_section(parser_helper_t *ctx, char *name);
+static section_t *pop_section(parser_helper_t *ctx);
+static void add_section(parser_helper_t *ctx, section_t *section);
+static void add_setting(parser_helper_t *ctx, kv_t *kv);
+
+/**
+ * Make sure to call lexer with the proper context
+ */
+#undef yylex
+static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
+{
+	return settings_parser_lex(lvalp, ctx->scanner);
+}
+
+%}
+%debug
+
+/* generate verbose error messages */
+%error-verbose
+/* generate a reentrant parser */
+%define api.pure
+/* prefix function/variable declarations */
+%name-prefix "settings_parser_"
+
+/* interact properly with the reentrant lexer */
+%lex-param {parser_helper_t *ctx}
+%parse-param {parser_helper_t *ctx}
+
+/* types for terminal symbols... (can't use the typedef'd types) */
+%union {
+	char *s;
+	struct section_t *sec;
+	struct kv_t *kv;
+}
+%token <s> NAME STRING
+%token NEWLINE
+
+/* ...and other symbols */
+%type <s> value valuepart
+%type <sec> section_start section
+%type <kv> setting
+
+/* properly destroy string tokens that are strdup()ed on error */
+%destructor { free($$); } NAME STRING value valuepart
+/* properly destroy parse results on error */
+%destructor { pop_section(ctx); settings_section_destroy($$, NULL); } section_start section
+%destructor { settings_kv_destroy($$, NULL); } setting
+
+/* there are two shift/reduce conflicts because of the "NAME = NAME" and
+ * "NAME {" ambiguity, and the "NAME =" rule) */
+%expect 2
+
+%%
+
+/**
+ * strongswan.conf grammar rules
+ */
+statements:
+	/* empty */
+	| statements NEWLINE
+	| statements statement
+	;
+
+statement:
+	section
+	{
+		add_section(ctx, $section);
+	}
+	| setting
+	{
+		add_setting(ctx, $setting);
+	}
+	;
+
+section:
+	section_start statements '}'
+	{
+		pop_section(ctx);
+		$$ = $section_start;
+	}
+	;
+
+section_start:
+	NAME '{'
+	{
+		$$ = push_section(ctx, $NAME);
+	}
+	|
+	NAME NEWLINE '{'
+	{
+		$$ = push_section(ctx, $NAME);
+	}
+	;
+
+setting:
+	NAME '=' value
+	{
+		$$ = settings_kv_create($NAME, $value);
+	}
+	|
+	NAME '='
+	{
+		$$ = settings_kv_create($NAME, NULL);
+	}
+	;
+
+value:
+	valuepart
+	| value valuepart
+	{	/* just put a single space between them, use strings for more */
+		if (asprintf(&$$, "%s %s", $1, $2) < 0)
+		{
+			free($1);
+			free($2);
+			YYERROR;
+		}
+		free($1);
+		free($2);
+	}
+	;
+
+valuepart:
+	NAME
+	| STRING
+	;
+
+%%
+
+/**
+ * Referenced by the generated parser
+ */
+static void settings_parser_error(parser_helper_t *ctx, const char *s)
+{
+	char *text = settings_parser_get_text(ctx->scanner);
+	int len = settings_parser_get_leng(ctx->scanner);
+
+	if (len && text[len-1] == '\n')
+	{	/* cut off newline at the end to avoid muti-line log messages */
+		len--;
+	}
+	PARSER_DBG1(ctx, "%s [%.*s]", s, len, text);
+}
+
+/**
+ * Create a section and push it to the stack (the name is adopted), returns
+ * the created section
+ */
+static section_t *push_section(parser_helper_t *ctx, char *name)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *section;
+
+	section = settings_section_create(name);
+	array_insert(sections, ARRAY_TAIL, section);
+	return section;
+}
+
+/**
+ * Removes the top section of the stack and returns it
+ */
+static section_t *pop_section(parser_helper_t *ctx)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *section;
+
+	array_remove(sections, ARRAY_TAIL, &section);
+	return section;
+}
+
+/**
+ * Adds the given section to the section on top of the stack
+ */
+static void add_section(parser_helper_t *ctx, section_t *section)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *parent;
+
+	array_get(sections, ARRAY_TAIL, &parent);
+	settings_section_add(parent, section, NULL);
+}
+
+/**
+ * Adds the given key/value pair to the section on top of the stack
+ */
+static void add_setting(parser_helper_t *ctx, kv_t *kv)
+{
+	array_t *sections = (array_t*)ctx->context;
+	section_t *section;
+
+	array_get(sections, ARRAY_TAIL, &section);
+	settings_kv_add(section, kv, NULL);
+}
+
+/**
+ * Parse the given file and add all sections and key/value pairs to the
+ * given section.
+ */
+bool settings_parser_parse_file(section_t *root, char *name)
+{
+	parser_helper_t *helper;
+	array_t *sections = NULL;
+	bool success = FALSE;
+
+	array_insert_create(&sections, ARRAY_TAIL, root);
+	helper = parser_helper_create(sections);
+	helper->get_lineno = settings_parser_get_lineno;
+	if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
+	{
+		helper->destroy(helper);
+		array_destroy(sections);
+		return FALSE;
+	}
+	helper->file_include(helper, name);
+	if (!settings_parser_open_next_file(helper))
+	{
+#ifdef STRONGSWAN_CONF
+		if (streq(name, STRONGSWAN_CONF))
+		{
+			DBG2(DBG_CFG, "failed to open config file '%s'", name);
+		}
+		else
+#endif
+		{
+			DBG1(DBG_CFG, "failed to open config file '%s'", name);
+		}
+	}
+	else
+	{
+		if (getenv("DEBUG_SETTINGS_PARSER"))
+		{
+			yydebug = 1;
+			settings_parser_set_debug(1, helper->scanner);
+		}
+		success = yyparse(helper) == 0;
+		if (!success)
+		{
+			DBG1(DBG_CFG, "invalid config file '%s'", name);
+		}
+	}
+	array_destroy(sections);
+	settings_parser_lex_destroy(helper->scanner);
+	helper->destroy(helper);
+	return success;
+}
diff --git a/src/libstrongswan/settings/settings_types.c b/src/libstrongswan/settings/settings_types.c
new file mode 100644
index 0000000..1256762
--- /dev/null
+++ b/src/libstrongswan/settings/settings_types.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2010-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 "settings_types.h"
+
+/*
+ * Described in header
+ */
+kv_t *settings_kv_create(char *key, char *value)
+{
+	kv_t *this;
+
+	INIT(this,
+		.key = key,
+		.value = value,
+	);
+	return this;
+}
+
+/*
+ * Described in header
+ */
+void settings_kv_destroy(kv_t *this, array_t *contents)
+{
+	free(this->key);
+	if (contents && this->value)
+	{
+		array_insert(contents, ARRAY_TAIL, this->value);
+	}
+	else
+	{
+		free(this->value);
+	}
+	free(this);
+}
+
+/*
+ * Described in header
+ */
+section_t *settings_section_create(char *name)
+{
+	section_t *this;
+
+	INIT(this,
+		.name = name,
+	);
+	return this;
+}
+
+static void section_destroy(section_t *section, int idx, array_t *contents)
+{
+	settings_section_destroy(section, contents);
+}
+
+static void kv_destroy(kv_t *kv, int idx, array_t *contents)
+{
+	settings_kv_destroy(kv, contents);
+}
+
+/*
+ * Described in header
+ */
+void settings_section_destroy(section_t *this, array_t *contents)
+{
+	array_destroy_function(this->sections, (void*)section_destroy, contents);
+	array_destroy(this->sections_order);
+	array_destroy_function(this->kv, (void*)kv_destroy, contents);
+	array_destroy(this->kv_order);
+	array_destroy(this->fallbacks);
+	free(this->name);
+	free(this);
+}
+
+/*
+ * Described in header
+ */
+void settings_kv_set(kv_t *kv, char *value, array_t *contents)
+{
+	if (value && kv->value && streq(value, kv->value))
+	{	/* no update required */
+		free(value);
+		return;
+	}
+
+	/* if the new value was shorter we could overwrite the existing one but that
+	 * could lead to reads of partially updated values from other threads that
+	 * have a pointer to the existing value, so we replace it anyway */
+	if (kv->value && contents)
+	{
+		array_insert(contents, ARRAY_TAIL, kv->value);
+	}
+	else
+	{
+		free(kv->value);
+	}
+	kv->value = value;
+}
+
+/*
+ * Described in header
+ */
+void settings_kv_add(section_t *section, kv_t *kv, array_t *contents)
+{
+	kv_t *found;
+
+	if (array_bsearch(section->kv, kv->key, settings_kv_find, &found) == -1)
+	{
+		array_insert_create(&section->kv, ARRAY_TAIL, kv);
+		array_sort(section->kv, settings_kv_sort, NULL);
+		array_insert_create(&section->kv_order, ARRAY_TAIL, kv);
+	}
+	else
+	{
+		settings_kv_set(found, kv->value, contents);
+		kv->value = NULL;
+		settings_kv_destroy(kv, NULL);
+	}
+}
+
+/*
+ * Add a section to the given parent, optionally remove settings/subsections
+ * not found when extending an existing section
+ */
+static void add_section(section_t *parent, section_t *section,
+						array_t *contents, bool purge)
+{
+	section_t *found;
+
+	if (array_bsearch(parent->sections, section->name, settings_section_find,
+					  &found) == -1)
+	{
+		array_insert_create(&parent->sections, ARRAY_TAIL, section);
+		array_sort(parent->sections, settings_section_sort, NULL);
+		array_insert_create(&parent->sections_order, ARRAY_TAIL, section);
+	}
+	else
+	{
+		settings_section_extend(found, section, contents, purge);
+		settings_section_destroy(section, contents);
+	}
+}
+
+/*
+ * Described in header
+ */
+void settings_section_add(section_t *parent, section_t *section,
+						  array_t *contents)
+{
+	add_section(parent, section, contents, FALSE);
+}
+
+/**
+ * Purge contents of a section, returns TRUE if section can be safely removed.
+ */
+static bool section_purge(section_t *this, array_t *contents)
+{
+	section_t *current;
+	int i, idx;
+
+	array_destroy_function(this->kv, (void*)kv_destroy, contents);
+	this->kv = NULL;
+	array_destroy(this->kv_order);
+	this->kv_order = NULL;
+	/* we ensure sections used as fallback, or configured with fallbacks (or
+	 * having any such subsections) are not removed */
+	for (i = array_count(this->sections_order) - 1; i >= 0; i--)
+	{
+		array_get(this->sections, i, &current);
+		if (section_purge(current, contents))
+		{
+			array_remove(this->sections_order, i, NULL);
+			idx = array_bsearch(this->sections, current->name,
+								settings_section_find, NULL);
+			array_remove(this->sections, idx, NULL);
+			settings_section_destroy(current, contents);
+		}
+	}
+	return !this->fallbacks && !array_count(this->sections);
+}
+
+/*
+ * Described in header
+ */
+void settings_section_extend(section_t *base, section_t *extension,
+							 array_t *contents, bool purge)
+{
+	enumerator_t *enumerator;
+	section_t *section;
+	kv_t *kv;
+	array_t *sections = NULL, *kvs = NULL;
+	int idx;
+
+	if (purge)
+	{	/* remove sections and settings in base not found in extension, the
+		 * others are removed too (from the _order list) so they can be inserted
+		 * in the order found in extension */
+		enumerator = array_create_enumerator(base->sections_order);
+		while (enumerator->enumerate(enumerator, (void**)&section))
+		{
+			if (array_bsearch(extension->sections, section->name,
+							  settings_section_find, NULL) == -1)
+			{
+				idx = array_bsearch(base->sections, section->name,
+									settings_section_find, NULL);
+				if (section_purge(section, contents))
+				{	/* only remove them if we can purge them */
+					array_remove(base->sections, idx, NULL);
+					array_remove_at(base->sections_order, enumerator);
+					settings_section_destroy(section, contents);
+				}
+			}
+			else
+			{
+				array_remove_at(base->sections_order, enumerator);
+				array_insert_create(&sections, ARRAY_TAIL, section);
+				array_sort(sections, settings_section_sort, NULL);
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		while (array_remove(base->kv_order, 0, &kv))
+		{
+			if (array_bsearch(extension->kv, kv->key, settings_kv_find,
+							  NULL) == -1)
+			{
+				idx = array_bsearch(base->kv, kv->key, settings_kv_find, NULL);
+				array_remove(base->kv, idx, NULL);
+				settings_kv_destroy(kv, contents);
+			}
+			else
+			{
+				array_insert_create(&kvs, ARRAY_TAIL, kv);
+				array_sort(kvs, settings_kv_sort, NULL);
+			}
+		}
+	}
+
+	while (array_remove(extension->sections_order, 0, &section))
+	{
+		idx = array_bsearch(sections, section->name,
+							settings_section_find, NULL);
+		if (idx != -1)
+		{
+			section_t *existing;
+
+			array_remove(sections, idx, &existing);
+			array_insert(base->sections_order, ARRAY_TAIL, existing);
+		}
+		idx = array_bsearch(extension->sections, section->name,
+							settings_section_find, NULL);
+		array_remove(extension->sections, idx, NULL);
+		add_section(base, section, contents, purge);
+	}
+
+	while (array_remove(extension->kv_order, 0, &kv))
+	{
+		idx = array_bsearch(kvs, kv->key, settings_kv_find, NULL);
+		if (idx != -1)
+		{
+			kv_t *existing;
+
+			array_remove(kvs, idx, &existing);
+			array_insert(base->kv_order, ARRAY_TAIL, existing);
+		}
+		idx = array_bsearch(extension->kv, kv->key, settings_kv_find, NULL);
+		array_remove(extension->kv, idx, NULL);
+		settings_kv_add(base, kv, contents);
+	}
+	array_destroy(sections);
+	array_destroy(kvs);
+}
+
+/*
+ * Described in header
+ */
+int settings_section_find(const void *a, const void *b)
+{
+	const char *key = a;
+	const section_t *item = b;
+	return strcmp(key, item->name);
+}
+
+/*
+ * Described in header
+ */
+int settings_section_sort(const void *a, const void *b, void *user)
+{
+	const section_t *sa = a, *sb = b;
+	return strcmp(sa->name, sb->name);
+}
+
+/*
+ * Described in header
+ */
+int settings_kv_find(const void *a, const void *b)
+{
+	const char *key = a;
+	const kv_t *item = b;
+	return strcmp(key, item->key);
+}
+
+/*
+ * Described in header
+ */
+int settings_kv_sort(const void *a, const void *b, void *user)
+{
+	const kv_t *kva = a, *kvb = b;
+	return strcmp(kva->key, kvb->key);
+}
diff --git a/src/libstrongswan/settings/settings_types.h b/src/libstrongswan/settings/settings_types.h
new file mode 100644
index 0000000..67299d8
--- /dev/null
+++ b/src/libstrongswan/settings/settings_types.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2010-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.
+ */
+
+/**
+ * Internal data types and functions shared between the parser and t.
+ *
+ * @defgroup settings_types settings_types
+ * @{ @ingroup settings
+ */
+
+#ifndef SETTINGS_TYPES_H_
+#define SETTINGS_TYPES_H_
+
+typedef struct kv_t kv_t;
+typedef struct section_t section_t;
+
+#include "collections/array.h"
+
+/**
+ * Key/value pair.
+ */
+struct kv_t {
+
+	/**
+	 * Key string, relative, not the full name.
+	 */
+	char *key;
+
+	/**
+	 * Value as string.
+	 */
+	char *value;
+};
+
+/**
+ * Section containing subsections and key value pairs.
+ */
+struct section_t {
+
+	/**
+	 * Name of the section.
+	 */
+	char *name;
+
+	/**
+	 * Fallback sections, as section_t.
+	 */
+	array_t *fallbacks;
+
+	/**
+	 * Subsections, as section_t.
+	 */
+	array_t *sections;
+
+	/**
+	 * Subsections in original order, as section_t (pointer to obj in sections).
+	 */
+	array_t *sections_order;
+
+	/**
+	 * Key value pairs, as kv_t.
+	 */
+	array_t *kv;
+
+	/**
+	 * Key value pairs in original order, as kv_t (pointer to obj in kv).
+	 */
+	array_t *kv_order;
+};
+
+/**
+ * Create a key/value pair.
+ *
+ * @param key		key (gets adopted)
+ * @param value		value (gets adopted)
+ * @return			allocated key/value pair
+ */
+kv_t *settings_kv_create(char *key, char *value);
+
+/**
+ * Destroy a key/value pair.
+ *
+ * @param this		key/value pair to destroy
+ * @param contents	optional array to store the value in
+ */
+void settings_kv_destroy(kv_t *this, array_t *contents);
+
+/**
+ * Set the value of the given key/value pair.
+ *
+ * @param kv		key/value pair
+ * @param value		new value (gets adopted), may be NULL
+ * @param contents	optional array to store replaced values in
+ */
+void settings_kv_set(kv_t *kv, char *value, array_t *contents);
+
+/**
+ * Add the given key/value pair to the given section.
+ *
+ * @param section	section to add pair to
+ * @param kv		key/value pair to add (gets adopted)
+ * @param contents	optional array to store replaced values in
+ */
+void settings_kv_add(section_t *section, kv_t *kv, array_t *contents);
+
+/**
+ * Create a section with the given name.
+ *
+ * @param name		name (gets adopted)
+ * @return			allocated section
+ */
+section_t *settings_section_create(char *name);
+
+/**
+ * Destroy a section.
+ *
+ * @param this		section to destroy
+ * @param contents	optional array to store values of removed key/value pairs
+ */
+void settings_section_destroy(section_t *this, array_t *contents);
+
+/**
+ * Add the given section to the given parent section.
+ *
+ * @param parent	section to add section to
+ * @param section	section to add (gets adopted)
+ * @param contents	optional array to store replaced values in
+ */
+void settings_section_add(section_t *parent, section_t *section,
+						  array_t *contents);
+
+/**
+ * Extend the first section with the values and sub-sections of the second
+ * section, from where they are consequently removed.
+ *
+ * @param base		base section to extend
+ * @param extension	section whose data is extracted
+ * @param contents	optional array to store replaced values in
+ * @param purge		TRUE to remove settings and sections not found in the
+ *					extension (unless (sub-)sections have/are fallbacks)
+ */
+void settings_section_extend(section_t *base, section_t *extension,
+							 array_t *contents, bool purge);
+
+/**
+ * Callback to find a section by name
+ */
+int settings_section_find(const void *a, const void *b);
+
+/**
+ * Callback to sort sections by name
+ */
+int settings_section_sort(const void *a, const void *b, void *user);
+
+/**
+ * Callback to find a key/value pair by key
+ */
+int settings_kv_find(const void *a, const void *b);
+
+/**
+ * Callback to sort kv pairs by key
+ */
+int settings_kv_sort(const void *a, const void *b, void *user);
+
+#endif /** SETTINGS_TYPES_H_ @}*/
diff --git a/src/libstrongswan/tests/Makefile.am b/src/libstrongswan/tests/Makefile.am
index 331a548..e8e8090 100644
--- a/src/libstrongswan/tests/Makefile.am
+++ b/src/libstrongswan/tests/Makefile.am
@@ -42,6 +42,7 @@ tests_SOURCES = tests.h tests.c \
   suites/test_host.c \
   suites/test_hasher.c \
   suites/test_crypter.c \
+  suites/test_crypto_factory.c \
   suites/test_pen.c \
   suites/test_asn1.c \
   suites/test_asn1_parser.c \
@@ -52,7 +53,7 @@ tests_SOURCES = tests.h tests.c \
 tests_CFLAGS = \
   -I$(top_srcdir)/src/libstrongswan \
   -I$(top_srcdir)/src/libstrongswan/tests \
-  -DPLUGINDIR=\""$(top_builddir)/src/libstrongswan/plugins\"" \
+  -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
   -DPLUGINS=\""${s_plugins}\"" \
   @COVERAGE_CFLAGS@
 
diff --git a/src/libstrongswan/tests/Makefile.in b/src/libstrongswan/tests/Makefile.in
index e58831c..1d2d5eb 100644
--- a/src/libstrongswan/tests/Makefile.in
+++ b/src/libstrongswan/tests/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -138,6 +138,7 @@ am_tests_OBJECTS = tests-tests.$(OBJEXT) \
 	suites/tests-test_host.$(OBJEXT) \
 	suites/tests-test_hasher.$(OBJEXT) \
 	suites/tests-test_crypter.$(OBJEXT) \
+	suites/tests-test_crypto_factory.$(OBJEXT) \
 	suites/tests-test_pen.$(OBJEXT) \
 	suites/tests-test_asn1.$(OBJEXT) \
 	suites/tests-test_asn1_parser.$(OBJEXT) \
@@ -295,6 +296,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -313,6 +315,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -340,6 +343,7 @@ 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@
@@ -431,6 +435,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -479,6 +484,7 @@ tests_SOURCES = tests.h tests.c \
   suites/test_host.c \
   suites/test_hasher.c \
   suites/test_crypter.c \
+  suites/test_crypto_factory.c \
   suites/test_pen.c \
   suites/test_asn1.c \
   suites/test_asn1_parser.c \
@@ -489,7 +495,7 @@ tests_SOURCES = tests.h tests.c \
 tests_CFLAGS = \
   -I$(top_srcdir)/src/libstrongswan \
   -I$(top_srcdir)/src/libstrongswan/tests \
-  -DPLUGINDIR=\""$(top_builddir)/src/libstrongswan/plugins\"" \
+  -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
   -DPLUGINS=\""${s_plugins}\"" \
   @COVERAGE_CFLAGS@
 
@@ -613,6 +619,8 @@ suites/tests-test_hasher.$(OBJEXT): suites/$(am__dirstamp) \
 	suites/$(DEPDIR)/$(am__dirstamp)
 suites/tests-test_crypter.$(OBJEXT): suites/$(am__dirstamp) \
 	suites/$(DEPDIR)/$(am__dirstamp)
+suites/tests-test_crypto_factory.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
 suites/tests-test_pen.$(OBJEXT): suites/$(am__dirstamp) \
 	suites/$(DEPDIR)/$(am__dirstamp)
 suites/tests-test_asn1.$(OBJEXT): suites/$(am__dirstamp) \
@@ -649,6 +657,7 @@ distclean-compile:
 @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_chunk.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_crypter.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_crypto_factory.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_ecdsa.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_enum.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/tests-test_enumerator.Po at am__quote@
@@ -1039,6 +1048,20 @@ suites/tests-test_crypter.obj: suites/test_crypter.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_crypter.obj `if test -f 'suites/test_crypter.c'; then $(CYGPATH_W) 'suites/test_crypter.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_crypter.c'; fi`
 
+suites/tests-test_crypto_factory.o: suites/test_crypto_factory.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_crypto_factory.o -MD -MP -MF suites/$(DEPDIR)/tests-test_crypto_factory.Tpo -c -o suites/tests-test_crypto_factory.o `test -f 'suites/test_crypto_factory.c' || echo '$(srcdir)/'`suites/test_crypto_factory.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_crypto_factory.Tpo suites/$(DEPDIR)/tests-test_crypto_factory.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_crypto_factory.c' object='suites/tests-test_crypto_factory.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_crypto_factory.o `test -f 'suites/test_crypto_factory.c' || echo '$(srcdir)/'`suites/test_crypto_factory.c
+
+suites/tests-test_crypto_factory.obj: suites/test_crypto_factory.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_crypto_factory.obj -MD -MP -MF suites/$(DEPDIR)/tests-test_crypto_factory.Tpo -c -o suites/tests-test_crypto_factory.obj `if test -f 'suites/test_crypto_factory.c'; then $(CYGPATH_W) 'suites/test_crypto_factory.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_crypto_factory.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_crypto_factory.Tpo suites/$(DEPDIR)/tests-test_crypto_factory.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_crypto_factory.c' object='suites/tests-test_crypto_factory.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_crypto_factory.obj `if test -f 'suites/test_crypto_factory.c'; then $(CYGPATH_W) 'suites/test_crypto_factory.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_crypto_factory.c'; fi`
+
 suites/tests-test_pen.o: suites/test_pen.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_CFLAGS) $(CFLAGS) -MT suites/tests-test_pen.o -MD -MP -MF suites/$(DEPDIR)/tests-test_pen.Tpo -c -o suites/tests-test_pen.o `test -f 'suites/test_pen.c' || echo '$(srcdir)/'`suites/test_pen.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/tests-test_pen.Tpo suites/$(DEPDIR)/tests-test_pen.Po
diff --git a/src/libstrongswan/tests/suites/test_asn1.c b/src/libstrongswan/tests/suites/test_asn1.c
index d0cd7e6..ac7c551 100644
--- a/src/libstrongswan/tests/suites/test_asn1.c
+++ b/src/libstrongswan/tests/suites/test_asn1.c
@@ -335,8 +335,8 @@ START_TEST(test_asn1_length)
 
 	/* largest chunk on 32 bit system */
 	a = chunk_from_chars(0x04, 0x84, 0xff, 0xff, 0xff, 0xf9, 0xaa);
-	a.len = 4294967295;
-	ck_assert(asn1_length(&a) == 4294967289);
+	a.len = 4294967295U;
+	ck_assert(asn1_length(&a) == 4294967289U);
 
 }
 END_TEST
diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c
index 34ace28..b33d70e 100644
--- a/src/libstrongswan/tests/suites/test_chunk.c
+++ b/src/libstrongswan/tests/suites/test_chunk.c
@@ -790,7 +790,11 @@ END_TEST
 START_TEST(test_chunk_map)
 {
 	chunk_t *map, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05);
+#ifdef WIN32
+	char *path = "C:\\Windows\\Temp\\strongswan-chunk-map-test";
+#else
 	char *path = "/tmp/strongswan-chunk-map-test";
+#endif
 
 	ck_assert(chunk_write(contents, path, 022, TRUE));
 
@@ -827,7 +831,11 @@ END_TEST
 START_TEST(test_chunk_from_fd_file)
 {
 	chunk_t in, contents = chunk_from_chars(0x01,0x02,0x03,0x04,0x05);
+#ifdef WIN32
+	char *path = "C:\\Windows\\Temp\\strongswan-chunk-fd-test";
+#else
 	char *path = "/tmp/strongswan-chunk-fd-test";
+#endif
 	int fd;
 
 	ck_assert(chunk_write(contents, path, 022, TRUE));
@@ -849,7 +857,7 @@ START_TEST(test_chunk_from_fd_skt)
 	int s[2];
 
 	ck_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0);
-	ck_assert(write(s[1], contents.ptr, contents.len) == contents.len);
+	ck_assert_int_eq(send(s[1], contents.ptr, contents.len, 0), contents.len);
 	close(s[1]);
 	ck_assert_msg(chunk_from_fd(s[0], &in), "%s", strerror(errno));
 	close(s[0]);
@@ -866,7 +874,7 @@ void *chunk_from_fd_run(void *data)
 
 	for (i = 0; i < FROM_FD_COUNT; i++)
 	{
-		ck_assert(write(fd, &i, sizeof(i)) == sizeof(i));
+		ck_assert(send(fd, &i, sizeof(i), 0) == sizeof(i));
 	}
 	close(fd);
 	return NULL;
diff --git a/src/libstrongswan/tests/suites/test_crypto_factory.c b/src/libstrongswan/tests/suites/test_crypto_factory.c
new file mode 100644
index 0000000..94f45da
--- /dev/null
+++ b/src/libstrongswan/tests/suites/test_crypto_factory.c
@@ -0,0 +1,312 @@
+/*
+ * 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_suite.h"
+
+#include <crypto/crypto_factory.h>
+
+static rng_t *rng_create(rng_quality_t quality)
+{
+	rng_quality_t *q = malloc_thing(rng_quality_t);
+	*q = quality;
+	return (rng_t*)q;
+}
+
+static rng_t *rng_create_weak(rng_quality_t quality)
+{
+	ck_assert(quality == RNG_WEAK);
+	return rng_create(RNG_WEAK);
+}
+
+static rng_t *rng_create_strong(rng_quality_t quality)
+{
+	ck_assert(quality <= RNG_STRONG);
+	return rng_create(RNG_STRONG);
+}
+
+static rng_t *rng_create_true(rng_quality_t quality)
+{
+	ck_assert(quality <= RNG_TRUE);
+	return rng_create(RNG_TRUE);
+}
+
+static rng_t *rng_create_true_second(rng_quality_t quality)
+{
+	fail("should never be called");
+	return rng_create(RNG_TRUE);
+}
+
+static rng_quality_t rng_weak = RNG_WEAK;
+static rng_quality_t rng_strong = RNG_STRONG;
+static rng_quality_t rng_true = RNG_TRUE;
+
+static struct {
+	rng_quality_t *exp_weak;
+	rng_quality_t *exp_strong;
+	rng_quality_t *exp_true;
+	struct {
+		rng_quality_t *q;
+		rng_constructor_t create;
+	} data[4];
+} rng_data[] = {
+	{ NULL, NULL, NULL, {
+		{ NULL, NULL }
+	}},
+	{ &rng_weak, NULL, NULL, {
+		{ &rng_weak, rng_create_weak },
+		{ NULL, NULL }
+	}},
+	{ &rng_strong, &rng_strong, NULL, {
+		{ &rng_strong, rng_create_strong },
+		{ NULL, NULL }
+	}},
+	{ &rng_true, &rng_true, &rng_true, {
+		{ &rng_true, rng_create_true },
+		{ NULL, NULL }
+	}},
+	{ &rng_true, &rng_true, &rng_true, {
+		{ &rng_true, rng_create_true },
+		{ &rng_true, rng_create_true_second },
+		{ NULL, NULL }
+	}},
+	{ &rng_weak, &rng_true, &rng_true, {
+		{ &rng_weak, rng_create_weak },
+		{ &rng_true, rng_create_true },
+		{ NULL, NULL }
+	}},
+	{ &rng_weak, &rng_strong, &rng_true, {
+		{ &rng_true, rng_create_true },
+		{ &rng_strong, rng_create_strong },
+		{ &rng_weak, rng_create_weak },
+		{ NULL, NULL }
+	}},
+	{ &rng_weak, &rng_strong, &rng_true, {
+		{ &rng_weak, rng_create_weak },
+		{ &rng_strong, rng_create_strong },
+		{ &rng_true, rng_create_true },
+		{ NULL, NULL }
+	}},
+};
+
+static void verify_rng(crypto_factory_t *factory, rng_quality_t request,
+					   rng_quality_t *expected)
+{
+	rng_quality_t *res;
+
+	res = (rng_quality_t*)factory->create_rng(factory, request);
+	if (!expected)
+	{
+		ck_assert(!res);
+	}
+	else
+	{
+		ck_assert(res);
+		ck_assert_int_eq(*expected, *res);
+		free(res);
+	}
+}
+
+START_TEST(test_create_rng)
+{
+	crypto_factory_t *factory;
+	int i;
+
+	factory = crypto_factory_create();
+	for (i = 0; rng_data[_i].data[i].q; i++)
+	{
+		ck_assert(factory->add_rng(factory, *rng_data[_i].data[i].q, "test",
+								   rng_data[_i].data[i].create));
+	}
+	verify_rng(factory, RNG_WEAK, rng_data[_i].exp_weak);
+	verify_rng(factory, RNG_STRONG, rng_data[_i].exp_strong);
+	verify_rng(factory, RNG_TRUE, rng_data[_i].exp_true);
+	for (i = 0; rng_data[_i].data[i].q; i++)
+	{
+		factory->remove_rng(factory, rng_data[_i].data[i].create);
+	}
+	factory->destroy(factory);
+}
+END_TEST
+
+static diffie_hellman_t *dh_create(char *plugin)
+{
+	return (diffie_hellman_t*)plugin;
+}
+
+static diffie_hellman_t *dh_create_modp1024(diffie_hellman_group_t group, ...)
+{
+	ck_assert(group == MODP_1024_BIT);
+	return dh_create("plugin1");
+}
+
+static diffie_hellman_t *dh_create_modp1024_second(diffie_hellman_group_t group,
+												   ...)
+{
+	ck_assert(group == MODP_1024_BIT);
+	return dh_create("plugin2");
+}
+
+static diffie_hellman_t *dh_create_modp2048(diffie_hellman_group_t group, ...)
+{
+	ck_assert(group == MODP_2048_BIT);
+	return dh_create("plugin1");
+}
+
+static diffie_hellman_t *dh_create_modp2048_second(diffie_hellman_group_t group,
+												   ...)
+{
+	ck_assert(group == MODP_2048_BIT);
+	return dh_create("plugin2");
+}
+
+static struct {
+	char *exp1024;
+	char *exp2048;
+	struct {
+		diffie_hellman_group_t g;
+		dh_constructor_t create;
+		char *plugin;
+	} data[4];
+} dh_data[] = {
+	{ NULL, NULL, {
+		{ MODP_NONE, NULL, NULL }
+	}},
+	{ "plugin1", NULL, {
+		{ MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+		{ MODP_NONE, NULL, NULL }
+	}},
+	{ "plugin1", NULL, {
+		{ MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+		{ MODP_1024_BIT, dh_create_modp1024_second, "plugin2" },
+		{ MODP_NONE, NULL, NULL }
+	}},
+	{ "plugin2", NULL, {
+		{ MODP_1024_BIT, dh_create_modp1024_second, "plugin2" },
+		{ MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+		{ MODP_NONE, NULL, NULL }
+	}},
+	{ "plugin1", "plugin1", {
+		{ MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+		{ MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+		{ MODP_NONE, NULL }
+	}},
+	{ "plugin1", "plugin1", {
+		{ MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+		{ MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+		{ MODP_NONE, NULL }
+	}},
+	{ "plugin1", "plugin1", {
+		{ MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+		{ MODP_2048_BIT, dh_create_modp2048_second, "plugin2" },
+		{ MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+		{ MODP_NONE, NULL }
+	}},
+	{ "plugin1", "plugin2", {
+		{ MODP_2048_BIT, dh_create_modp2048_second, "plugin2" },
+		{ MODP_2048_BIT, dh_create_modp2048, "plugin1" },
+		{ MODP_1024_BIT, dh_create_modp1024, "plugin1" },
+		{ MODP_NONE, NULL }
+	}},
+};
+
+static void verify_dh(crypto_factory_t *factory, diffie_hellman_group_t request,
+					  char *expected)
+{
+	char *plugin;
+
+	plugin = (char*)factory->create_dh(factory, request);
+	if (!expected)
+	{
+		ck_assert(!plugin);
+	}
+	else
+	{
+		ck_assert(plugin);
+		ck_assert_str_eq(expected, plugin);
+	}
+}
+
+START_TEST(test_create_dh)
+{
+	enumerator_t *enumerator;
+	crypto_factory_t *factory;
+	diffie_hellman_group_t group;
+	char *plugin;
+	int i, len = 0;
+
+
+	factory = crypto_factory_create();
+	for (i = 0; dh_data[_i].data[i].g != MODP_NONE; i++)
+	{
+		ck_assert(factory->add_dh(factory, dh_data[_i].data[i].g,
+								  dh_data[_i].data[i].plugin,
+								  dh_data[_i].data[i].create));
+	}
+	verify_dh(factory, MODP_1024_BIT, dh_data[_i].exp1024);
+	verify_dh(factory, MODP_2048_BIT, dh_data[_i].exp2048);
+
+	len = countof(dh_data[_i].data);
+	enumerator = factory->create_dh_enumerator(factory);
+	for (i = 0; enumerator->enumerate(enumerator, &group, &plugin) && i < len;)
+	{
+		ck_assert_int_eq(dh_data[_i].data[i].g, group);
+		while (dh_data[_i].data[i].g == group)
+		{	/* skip other entries by the same group */
+			i++;
+		}
+		switch (group)
+		{
+			case MODP_1024_BIT:
+				ck_assert(dh_data[_i].exp1024);
+				ck_assert_str_eq(dh_data[_i].exp1024, plugin);
+				break;
+			case MODP_2048_BIT:
+				ck_assert(dh_data[_i].exp2048);
+				ck_assert_str_eq(dh_data[_i].exp2048, plugin);
+				break;
+			default:
+				fail("unexpected DH group");
+				break;
+		}
+	}
+	ck_assert(!enumerator->enumerate(enumerator));
+	ck_assert_int_eq(dh_data[_i].data[i].g, MODP_NONE);
+	enumerator->destroy(enumerator);
+
+	for (i = 0; dh_data[_i].data[i].g != MODP_NONE; i++)
+	{
+		factory->remove_dh(factory, dh_data[_i].data[i].create);
+	}
+	factory->destroy(factory);
+}
+END_TEST
+
+Suite *crypto_factory_suite_create()
+{
+	Suite *s;
+	TCase *tc;
+
+	s = suite_create("crypto-factory");
+
+	tc = tcase_create("create_rng");
+	tcase_add_loop_test(tc, test_create_rng, 0, countof(rng_data));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("create_dh");
+	tcase_add_loop_test(tc, test_create_dh, 0, countof(dh_data));
+	suite_add_tcase(s, tc);
+
+	return s;
+}
diff --git a/src/libstrongswan/tests/suites/test_enum.c b/src/libstrongswan/tests/suites/test_enum.c
index 990d9cf..b48b51c 100644
--- a/src/libstrongswan/tests/suites/test_enum.c
+++ b/src/libstrongswan/tests/suites/test_enum.c
@@ -15,7 +15,6 @@
 
 #include "test_suite.h"
 
-#include <utils/enum.h>
 #include <utils/utils.h>
 
 /*******************************************************************************
@@ -121,41 +120,50 @@ END_TEST
  */
 
 static struct {
+	bool found;
 	int val;
 	char *str;
 } enum_tests_cont[] = {
-	{CONT1, "CONT1"},
-	{CONT2, "CONT2"},
-	{CONT2, "CoNt2"},
-	{CONT3, "CONT3"},
-	{CONT4, "CONT4"},
-	{CONT5, "CONT5"},
-	{-1, "asdf"},
-	{-1, ""},
-	{-1, NULL},
+	{TRUE, CONT1, "CONT1"},
+	{TRUE, CONT2, "CONT2"},
+	{TRUE, CONT2, "CoNt2"},
+	{TRUE, CONT3, "CONT3"},
+	{TRUE, CONT4, "CONT4"},
+	{TRUE, CONT5, "CONT5"},
+	{FALSE, 0, "asdf"},
+	{FALSE, 0, ""},
+	{FALSE, 0, NULL},
 }, enum_tests_split[] = {
-	{SPLIT1, "SPLIT1"},
-	{SPLIT1, "split1"},
-	{SPLIT2, "SPLIT2"},
-	{SPLIT2, "SpLiT2"},
-	{SPLIT3, "SPLIT3"},
-	{SPLIT4, "SPLIT4"},
-	{SPLIT5, "SPLIT5"},
-	{-1, "asdf"},
-	{-1, ""},
-	{-1, NULL},
+	{TRUE, SPLIT1, "SPLIT1"},
+	{TRUE, SPLIT1, "split1"},
+	{TRUE, SPLIT2, "SPLIT2"},
+	{TRUE, SPLIT2, "SpLiT2"},
+	{TRUE, SPLIT3, "SPLIT3"},
+	{TRUE, SPLIT4, "SPLIT4"},
+	{TRUE, SPLIT5, "SPLIT5"},
+	{FALSE, 0, "asdf"},
+	{FALSE, 0, ""},
+	{FALSE, 0, NULL},
 };
 
 START_TEST(test_enum_from_name_cont)
 {
-	int val = enum_from_name(test_enum_cont_names, enum_tests_cont[_i].str);
+	int val = 0;
+	bool found;
+
+	found = enum_from_name(test_enum_cont_names, enum_tests_cont[_i].str, &val);
+	ck_assert(enum_tests_cont[_i].found == found);
 	ck_assert_int_eq(val, enum_tests_cont[_i].val);
 }
 END_TEST
 
 START_TEST(test_enum_from_name_split)
 {
-	int val = enum_from_name(test_enum_split_names, enum_tests_split[_i].str);
+	int val = 0;
+	bool found;
+
+	found = enum_from_name(test_enum_split_names, enum_tests_split[_i].str, &val);
+	ck_assert(enum_tests_split[_i].found == found);
 	ck_assert_int_eq(val, enum_tests_split[_i].val);
 }
 END_TEST
diff --git a/src/libstrongswan/tests/suites/test_fetch_http.c b/src/libstrongswan/tests/suites/test_fetch_http.c
index 8749ff3..9f1eef2 100644
--- a/src/libstrongswan/tests/suites/test_fetch_http.c
+++ b/src/libstrongswan/tests/suites/test_fetch_http.c
@@ -18,6 +18,8 @@
 #include <unistd.h>
 #include <time.h>
 
+#define HTTP_SUCCESS(status) ((status) >= 200 && (status) < 300)
+
 /**
  * HTTP test definition
  */
@@ -42,6 +44,8 @@ typedef struct {
 	void *res;
 	/* length of response data */
 	int res_len;
+	/* status code, defaults to 200 */
+	u_int code;
 } test_service_t;
 
 static char large[] = {
@@ -147,40 +151,50 @@ static bool servicing(void *data, stream_t *stream)
 		ck_assert(memeq(body, test->req, test->req_len));
 	}
 
+	if (!test->code)
+	{
+		test->code = 200;
+	}
+
 	/* response headers */
-	snprintf(buf, sizeof(buf), "HTTP/1.%u 200 OK\r\n", test->minor);
+	snprintf(buf, sizeof(buf), "HTTP/1.%u %u OK\r\n", test->minor, test->code);
 	ck_assert(stream->write_all(stream, buf, strlen(buf)));
+
+	/* if the response code indicates an error the following write operations
+	 * might fail because the client already terminated the TCP connection */
+#define may_fail(test, op) ck_assert(op || !HTTP_SUCCESS(test->code))
+
 	t = time(NULL);
 	gmtime_r(&t, &tm);
 	strftime(buf, sizeof(buf), "%a, %d %b %Y %T %z", &tm);
-	ck_assert(stream->write_all(stream, buf, strlen(buf)));
+	may_fail(test, stream->write_all(stream, buf, strlen(buf)));
 	snprintf(buf, sizeof(buf), "Server: strongSwan unit test\r\n");
-	ck_assert(stream->write_all(stream, buf, strlen(buf)));
+	may_fail(test, stream->write_all(stream, buf, strlen(buf)));
 
 	/* rest of response headers */
 	snprintf(buf, sizeof(buf), "Content-Type: text/plain\r\n");
-	ck_assert(stream->write_all(stream, buf, strlen(buf)));
+	may_fail(test, stream->write_all(stream, buf, strlen(buf)));
 	snprintf(buf, sizeof(buf), "Content-Length: %u\r\n", test->res_len);
-	ck_assert(stream->write_all(stream, buf, strlen(buf)));
+	may_fail(test, stream->write_all(stream, buf, strlen(buf)));
 	snprintf(buf, sizeof(buf), "Connection: close\r\n");
-	ck_assert(stream->write_all(stream, buf, strlen(buf)));
+	may_fail(test, stream->write_all(stream, buf, strlen(buf)));
 	snprintf(buf, sizeof(buf), "\r\n");
-	ck_assert(stream->write_all(stream, buf, strlen(buf)));
+	may_fail(test, stream->write_all(stream, buf, strlen(buf)));
 
 	/* response body */
-	ck_assert(stream->write_all(stream, test->res, test->res_len));
+	may_fail(test, stream->write_all(stream, test->res, test->res_len));
 	return FALSE;
 }
 
 static test_service_t gtests[] = {
 	{ "GET", 1, "127.0.0.1", 6543, "/a/test/?b=c", NULL,
-	  NULL, 0, "\x12\x34", 2 },
+	  NULL, 0, "\x12\x34", 2, 0 },
 	{ "GET", 0, "localhost", 6543, "/", NULL,
-	  NULL, 0, NULL, 0 },
+	  NULL, 0, NULL, 0, 0 },
 	{ "GET", 0, "127.0.0.1", 6543, "/largefile", NULL,
-	  NULL, 0, large, sizeof(large) },
+	  NULL, 0, large, sizeof(large), 0 },
 	{ "GET", 1, "[::1]", 6543, "/ipv6-url", NULL,
-	  NULL, 0, "\x00\r\n\r\x00testdatablabla", 20 },
+	  NULL, 0, "\x00\r\n\r\x00testdatablabla", 20, 0 },
 };
 
 START_TEST(test_get)
@@ -215,11 +229,11 @@ END_TEST
 
 static test_service_t ptests[] = {
 	{ "POST", 1, "127.0.0.1", 6543, "/a/test/?b=c", "application/binary",
-	  "\x23\x45", 2, "\x12\x34", 2 },
+	  "\x23\x45", 2, "\x12\x34", 2, 0 },
 	{ "POST", 0, "localhost", 6543, "/largefile", "application/x-large",
-	  large, sizeof(large), large, sizeof(large) },
+	  large, sizeof(large), large, sizeof(large), 0 },
 	{ "POST", 1, "[::1]", 6543, "/ipv6-url", "text/plain",
-	  "\x00\r\n\r\x00testdatablabla", 20, "\x00\r\n\r\x00testdatablabla", 20 },
+	  "\x00\r\n\r\x00testdatablabla", 20, "\x00\r\n\r\x00testdatablabla", 20, 0 },
 };
 
 START_TEST(test_post)
@@ -254,6 +268,42 @@ START_TEST(test_post)
 }
 END_TEST
 
+
+static test_service_t rtests[] = {
+	{ "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 200 },
+	{ "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 204 },
+	{ "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 400 },
+	{ "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 404 },
+	{ "GET", 1, "localhost", 6544, "/", NULL, NULL, 0, NULL, 0, 500 },
+};
+
+START_TEST(test_response_code)
+{
+	stream_service_t *service;
+	status_t status;
+	chunk_t data = chunk_empty;
+	char uri[256];
+	u_int code;
+
+	lib->processor->set_threads(lib->processor, 8);
+
+	snprintf(uri, sizeof(uri), "tcp://%s:%u", rtests[_i].host, rtests[_i].port);
+	service = lib->streams->create_service(lib->streams, uri, 1);
+	ck_assert(service != NULL);
+	service->on_accept(service, servicing, &rtests[_i], JOB_PRIO_HIGH, 0);
+
+	snprintf(uri, sizeof(uri), "http://%s:%u%s",
+			 rtests[_i].host, rtests[_i].port, rtests[_i].path);
+	status = lib->fetcher->fetch(lib->fetcher, uri, &data,
+								 FETCH_RESPONSE_CODE, &code, FETCH_END);
+	ck_assert_int_eq(status, HTTP_SUCCESS(rtests[_i].code) ? SUCCESS : FAILED);
+	ck_assert_int_eq(code, rtests[_i].code);
+	free(data.ptr);
+
+	service->destroy(service);
+}
+END_TEST
+
 Suite *fetch_http_suite_create()
 {
 	Suite *s;
@@ -269,5 +319,9 @@ Suite *fetch_http_suite_create()
 	tcase_add_loop_test(tc, test_post, 0, countof(ptests));
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("response code");
+	tcase_add_loop_test(tc, test_response_code, 0, countof(rtests));
+	suite_add_tcase(s, tc);
+
 	return s;
 }
diff --git a/src/libstrongswan/tests/suites/test_host.c b/src/libstrongswan/tests/suites/test_host.c
index 30b9eb9..6344208 100644
--- a/src/libstrongswan/tests/suites/test_host.c
+++ b/src/libstrongswan/tests/suites/test_host.c
@@ -286,8 +286,8 @@ END_TEST
 
 START_TEST(test_create_from_sockaddr_other)
 {
-	struct sockaddr_un addr = {
-		.sun_family = AF_UNIX,
+	struct sockaddr addr = {
+		.sa_family = AF_UNIX,
 	};
 	host_t *host;
 
diff --git a/src/libstrongswan/tests/suites/test_identification.c b/src/libstrongswan/tests/suites/test_identification.c
index edf53f0..5de7857 100644
--- a/src/libstrongswan/tests/suites/test_identification.c
+++ b/src/libstrongswan/tests/suites/test_identification.c
@@ -376,14 +376,14 @@ START_TEST(test_equals)
 							 "C=CH, E=moon at strongswan.org, CN=moon");
 
 	ck_assert(id_equals(a, "C=CH, E=moon at strongswan.org, CN=moon"));
-	ck_assert(id_equals(a, "C==CH, E==moon at strongswan.org,,, CN==moon"));
+	ck_assert(id_equals(a, "C==CH , E==moon at strongswan.org , CN==moon"));
 	ck_assert(id_equals(a, "  C=CH, E=moon at strongswan.org, CN=moon  "));
 	ck_assert(id_equals(a, "C=ch, E=moon at STRONGSWAN.ORG, CN=Moon"));
 	ck_assert(id_equals(a, "/C=CH/E=moon at strongswan.org/CN=moon"));
-	ck_assert(id_equals(a, "C=CH/E=moon at strongswan.org/CN=moon"));
-	ck_assert(id_equals(a, "C=CH/E=moon at strongswan.org,CN=moon"));
-	ck_assert(id_equals(a, "C=CH / E=moon at strongswan.org , CN=moon"));
+	ck_assert(id_equals(a, " / C=CH / E=moon at strongswan.org / CN=moon"));
 
+	ck_assert(!id_equals(a, "C=CH/E=moon at strongswan.org/CN=moon"));
+	ck_assert(!id_equals(a, "C=CH/E=moon at strongswan.org,CN=moon"));
 	ck_assert(!id_equals(a, "C=CH E=moon at strongswan.org CN=moon"));
 	ck_assert(!id_equals(a, "C=CN, E=moon at strongswan.org, CN=moon"));
 	ck_assert(!id_equals(a, "E=moon at strongswan.org, C=CH, CN=moon"));
diff --git a/src/libstrongswan/tests/suites/test_settings.c b/src/libstrongswan/tests/suites/test_settings.c
index 0964651..b9d429a 100644
--- a/src/libstrongswan/tests/suites/test_settings.c
+++ b/src/libstrongswan/tests/suites/test_settings.c
@@ -17,12 +17,16 @@
 
 #include <unistd.h>
 
-#include <utils/settings.h>
+#include <settings/settings.h>
 #include <utils/chunk.h>
 #include <utils/utils.h>
 #include <collections/linked_list.h>
 
+#ifdef WIN32
+static char *path = "C:\\Windows\\Temp\\strongswan-settings-test";
+#else
 static char *path = "/tmp/strongswan-settings-test";
+#endif
 static settings_t *settings;
 
 static void create_settings(chunk_t contents)
@@ -39,6 +43,7 @@ START_SETUP(setup_base_config)
 		"	# this gets overridden below\n"
 		"	key2 = val2\n"
 		"	none = \n"
+		"	empty = \"\"\n"
 		"	sub1 {\n"
 		"		key = value\n"
 		"		key2 = value2\n"
@@ -51,7 +56,8 @@ START_SETUP(setup_base_config)
 		"	sub% {\n"
 		"		id = %any\n"
 		"	}\n"
-		"	key2 = with spaces\n"
+		"	key2 = with space\n"
+		"	key3 = \"string with\\nnewline\"\n"
 		"}\n"
 		"out = side\n"
 		"other {\n"
@@ -79,7 +85,9 @@ START_TEST(test_get_str)
 	verify_string("val1", "main.key1");
 	verify_string("val1", "main..key1");
 	verify_string("val1", ".main.key1");
-	verify_string("with spaces", "main.key2");
+	verify_string("", "main.empty");
+	verify_string("with space", "main.key2");
+	verify_string("string with\nnewline", "main.key3");
 	verify_string("value", "main.sub1.key");
 	verify_string("value2", "main.sub1.key2");
 	verify_string("bar", "main.sub1.subsub.foo");
@@ -88,10 +96,8 @@ START_TEST(test_get_str)
 	verify_string("side", "out");
 	verify_string("other val", "other.key1");
 
-	/* FIXME: should this rather be undefined i.e. return the default value? */
-	verify_string("", "main.none");
-
-	verify_null("main.key3");
+	verify_null("main.none");
+	verify_null("main.key4");
 	verify_null("other.sub");
 }
 END_TEST
@@ -125,16 +131,35 @@ START_TEST(test_get_str_printf)
 	 * probably document it at least */
 	verify_null("main.%s%u.key%d", "sub", 1, 2);
 
-	verify_null("%s.%s%d", "main", "key", 3);
+	verify_null("%s.%s%d", "main", "key", 4);
 }
 END_TEST
 
 START_TEST(test_set_str)
 {
+	char *val1, *val2;
+
+	val1 = settings->get_str(settings, "main.key1", NULL);
+	ck_assert_str_eq("val1", val1);
 	settings->set_str(settings, "main.key1", "val");
 	verify_string("val", "main.key1");
+	/* the pointer we got before is still valid */
+	ck_assert_str_eq("val1", val1);
+
+	val2 = settings->get_str(settings, "main.key1", NULL);
+	ck_assert_str_eq("val", val2);
 	settings->set_str(settings, "main.key1", "longer value");
 	verify_string("longer value", "main.key1");
+	/* the pointers we got before are still valid */
+	ck_assert_str_eq("val1", val1);
+	ck_assert_str_eq("val", val2);
+
+	val1 = settings->get_str(settings, "main.key1", NULL);
+	settings->set_str(settings, "main.key1", "longer value");
+	val2 = settings->get_str(settings, "main.key1", NULL);
+	/* setting the same string should should get us the same pointer */
+	ck_assert(val1 == val2);
+
 	settings->set_str(settings, "main", "main val");
 	verify_string("main val", "main");
 	settings->set_str(settings, "main.sub1.new", "added");
@@ -183,6 +208,7 @@ START_SETUP(setup_bool_config)
 		"	key7 = disabled\n"
 		"	key8 = 0\n"
 		"	key9 = 5\n"
+		"	empty = \"\"\n"
 		"	none = \n"
 		"	foo = bar\n"
 		"}"));
@@ -203,6 +229,8 @@ START_TEST(test_get_bool)
 	verify_bool(FALSE, TRUE, "main.key7");
 	verify_bool(FALSE, TRUE, "main.key8");
 
+	verify_bool(FALSE, FALSE, "main.empty");
+	verify_bool(TRUE, TRUE, "main.empty");
 	verify_bool(FALSE, FALSE, "main.none");
 	verify_bool(TRUE, TRUE, "main.none");
 	verify_bool(FALSE, FALSE, "main.foo");
@@ -237,9 +265,9 @@ START_SETUP(setup_int_config)
 	create_settings(chunk_from_str(
 		"main {\n"
 		"	key1 = 5\n"
-		"	# gets cut off\n"
 		"	key2 = 5.5\n"
 		"	key3 = -42\n"
+		"	empty = \"\"\n"
 		"	none = \n"
 		"	foo1 = bar\n"
 		"	foo2 = bar13\n"
@@ -254,14 +282,14 @@ END_SETUP
 START_TEST(test_get_int)
 {
 	verify_int(5, 0, "main.key1");
-	verify_int(5, 0, "main.key2");
+	verify_int(0, 0, "main.key2");
 	verify_int(-42, 0, "main.key3");
 
-	/* FIXME: do we want this behavior? */
-	verify_int(0, 11, "main.none");
-	verify_int(0, 11, "main.foo1");
-	verify_int(0, 11, "main.foo2");
-	verify_int(13, 11, "main.foo3");
+	verify_int(11, 11, "main.empty");
+	verify_int(11, 11, "main.none");
+	verify_int(11, 11, "main.foo1");
+	verify_int(11, 11, "main.foo2");
+	verify_int(11, 11, "main.foo3");
 
 	verify_int(13, 13, "main.key4");
 	verify_int(-13, -13, "main");
@@ -291,6 +319,7 @@ START_SETUP(setup_double_config)
 		"	key2 = 5.5\n"
 		"	key3 = -42\n"
 		"	key4 = -42.5\n"
+		"	empty = \"\"\n"
 		"	none = \n"
 		"	foo1 = bar\n"
 		"	foo2 = bar13.5\n"
@@ -309,11 +338,11 @@ START_TEST(test_get_double)
 	verify_double(-42, 0, "main.key3");
 	verify_double(-42.5, 0, "main.key4");
 
-	/* FIXME: do we want this behavior? */
-	verify_double(0, 11.5, "main.none");
-	verify_double(0, 11.5, "main.foo1");
-	verify_double(0, 11.5, "main.foo2");
-	verify_double(13.5, 11.5, "main.foo3");
+	verify_double(11.5, 11.5, "main.empty");
+	verify_double(11.5, 11.5, "main.none");
+	verify_double(11.5, 11.5, "main.foo1");
+	verify_double(11.5, 11.5, "main.foo2");
+	verify_double(11.5, 11.5, "main.foo3");
 
 	verify_double(11.5, 11.5, "main.key5");
 	verify_double(-11.5, -11.5, "main");
@@ -341,10 +370,12 @@ START_SETUP(setup_time_config)
 {
 	create_settings(chunk_from_str(
 		"main {\n"
+		"	key0 = 5\n"
 		"	key1 = 5s\n"
 		"	key2 = 5m\n"
-		"	key3 = 5h\n"
-		"	key4 = 5d\n"
+		"	key3 = 5 h\n"
+		"	key4 = 5\td\n"
+		"	empty = \"\"\n"
 		"	none = \n"
 		"	foo1 = bar\n"
 		"	foo2 = bar13\n"
@@ -358,16 +389,17 @@ END_SETUP
 
 START_TEST(test_get_time)
 {
+	verify_time(5, 0, "main.key0");
 	verify_time(5, 0, "main.key1");
 	verify_time(300, 0, "main.key2");
 	verify_time(18000, 0, "main.key3");
 	verify_time(432000, 0, "main.key4");
 
-	/* FIXME: do we want this behavior? */
-	verify_time(0, 11, "main.none");
-	verify_time(0, 11, "main.foo1");
-	verify_time(0, 11, "main.foo2");
-	verify_time(13, 11, "main.foo3");
+	verify_time(11, 11, "main.empty");
+	verify_time(11, 11, "main.none");
+	verify_time(11, 11, "main.foo1");
+	verify_time(11, 11, "main.foo2");
+	verify_time(11, 11, "main.foo3");
 
 	verify_time(11, 11, "main.key5");
 	verify_time(11, 11, "main");
@@ -387,37 +419,21 @@ START_TEST(test_set_time)
 }
 END_TEST
 
-static bool verify_section(linked_list_t *verifier, char *section)
-{
-	enumerator_t *enumerator;
-	char *current;
-	bool result = FALSE;
-
-	enumerator = verifier->create_enumerator(verifier);
-	while (enumerator->enumerate(enumerator, &current))
-	{
-		if (streq(current, section))
-		{
-			verifier->remove_at(verifier, enumerator);
-			result = TRUE;
-			break;
-		}
-	}
-	enumerator->destroy(enumerator);
-	return result;
-}
-
 static void verify_sections(linked_list_t *verifier, char *parent)
 {
-	enumerator_t *enumerator;
-	char *section;
+	enumerator_t *enumerator, *ver;
+	char *section, *current;
 
 	enumerator = settings->create_section_enumerator(settings, parent);
-	while (enumerator->enumerate(enumerator, &section))
+	ver = verifier->create_enumerator(verifier);
+	while (enumerator->enumerate(enumerator, &section) &&
+		   ver->enumerate(ver, &current))
 	{
-		ck_assert(verify_section(verifier, section));
+		ck_assert_str_eq(section, current);
+		verifier->remove_at(verifier, ver);
 	}
 	enumerator->destroy(enumerator);
+	ver->destroy(ver);
 	ck_assert_int_eq(0, verifier->get_count(verifier));
 	verifier->destroy(verifier);
 }
@@ -429,8 +445,8 @@ START_TEST(test_section_enumerator)
 	verifier = linked_list_create_with_items("sub1", "sub%", NULL);
 	verify_sections(verifier, "main");
 
-	settings->set_str(settings, "main.sub2.new", "added");
-	verifier = linked_list_create_with_items("sub1", "sub%", "sub2", NULL);
+	settings->set_str(settings, "main.sub0.new", "added");
+	verifier = linked_list_create_with_items("sub1", "sub%", "sub0", NULL);
 	verify_sections(verifier, "main");
 
 	verifier = linked_list_create_with_items("subsub", NULL);
@@ -447,44 +463,27 @@ START_TEST(test_section_enumerator)
 }
 END_TEST
 
-static bool verify_key_value(linked_list_t *keys, linked_list_t *values,
-							 char *key, char *value)
+static void verify_key_values(linked_list_t *keys, linked_list_t *values,
+							  char *parent)
 {
-	enumerator_t *enum_keys, *enum_values;
-	char *current_key, *current_value;
-	bool result = FALSE;
+	enumerator_t *enumerator, *enum_keys, *enum_values;
+	char *key, *value, *current_key, *current_value;
 
+	enumerator = settings->create_key_value_enumerator(settings, parent);
 	enum_keys = keys->create_enumerator(keys);
 	enum_values = values->create_enumerator(values);
-	while (enum_keys->enumerate(enum_keys, &current_key) &&
+	while (enumerator->enumerate(enumerator, &key, &value) &&
+		   enum_keys->enumerate(enum_keys, &current_key) &&
 		   enum_values->enumerate(enum_values, &current_value))
 	{
-		if (streq(current_key, key))
-		{
-			ck_assert_str_eq(current_value, value);
-			keys->remove_at(keys, enum_keys);
-			values->remove_at(values, enum_values);
-			result = TRUE;
-			break;
-		}
+		ck_assert_str_eq(current_key, key);
+		ck_assert_str_eq(current_value, value);
+		keys->remove_at(keys, enum_keys);
+		values->remove_at(values, enum_values);
 	}
+	enumerator->destroy(enumerator);
 	enum_keys->destroy(enum_keys);
 	enum_values->destroy(enum_values);
-	return result;
-}
-
-static void verify_key_values(linked_list_t *keys, linked_list_t *values,
-							  char *parent)
-{
-	enumerator_t *enumerator;
-	char *key, *value;
-
-	enumerator = settings->create_key_value_enumerator(settings, parent);
-	while (enumerator->enumerate(enumerator, &key, &value))
-	{
-		ck_assert(verify_key_value(keys, values, key, value));
-	}
-	enumerator->destroy(enumerator);
 	ck_assert_int_eq(0, keys->get_count(keys));
 	keys->destroy(keys);
 	values->destroy(values);
@@ -494,8 +493,8 @@ START_TEST(test_key_value_enumerator)
 {
 	linked_list_t *keys, *values;
 
-	keys = linked_list_create_with_items("key1", "key2", "none", NULL);
-	values = linked_list_create_with_items("val1", "with spaces", "", NULL);
+	keys = linked_list_create_with_items("key1", "key2", "empty", "key3", NULL);
+	values = linked_list_create_with_items("val1", "with space", "", "string with\nnewline", NULL);
 	verify_key_values(keys, values, "main");
 
 	keys = linked_list_create_with_items("key", "key2", "subsub", NULL);
@@ -522,8 +521,13 @@ START_TEST(test_key_value_enumerator)
 }
 END_TEST
 
-#define include1 "/tmp/strongswan-settings-test-include1"
-#define include2 "/tmp/strongswan-settings-test-include2"
+#ifdef WIN32
+# define include1 "C:\\Windows\\Temp\\strongswan-settings-test-include1"
+# define include2 "C:\\Windows\\Temp\\strongswan-settings-test-include2"
+#else
+# define include1 "/tmp/strongswan-settings-test-include1"
+# define include2 "/tmp/strongswan-settings-test-include2"
+#endif
 
 START_SETUP(setup_include_config)
 {
@@ -531,6 +535,7 @@ START_SETUP(setup_include_config)
 		"main {\n"
 		"	key1 = n1\n"
 		"	key2 = n2\n"
+		"	key3 = val3\n"
 		"	none = \n"
 		"	sub1 {\n"
 		"		key3 = value\n"
@@ -563,13 +568,15 @@ static void verify_include()
 {
 	verify_string("n1", "main.key1");
 	verify_string("v2", "main.key2");
-	verify_string("", "main.none");
+	verify_string("val3", "main.key3");
 	verify_string("val", "main.sub1.key");
 	verify_string("v2", "main.sub1.key2");
 	verify_string("val", "main.sub1.sub1.key");
 	verify_string("value", "main.sub1.key3");
 	verify_string("value", "main.sub1.include");
 	verify_string("val3", "main.sub2.sub3");
+
+	verify_null("main.none");
 }
 
 START_TEST(test_include)
@@ -580,13 +587,13 @@ START_TEST(test_include)
 		"	key2 = val2\n"
 		"	none = x\n"
 		"	sub1 {\n"
+		"		include this/does/not/exist.conf\n"
 		"		include = value\n"
 		"		key2 = value2\n"
 		"		include " include2 "\n"
 		"	}\n"
 		"}\n"
-		"# currently there must be a newline after include statements\n"
-		"include " include1 "\n");
+		"include " include1);
 
 	create_settings(contents);
 	verify_include();
@@ -599,6 +606,7 @@ START_TEST(test_load_files)
 		"main {\n"
 		"	key1 = val1\n"
 		"	key2 = val2\n"
+		"	key3 = val3\n"
 		"	none = x\n"
 		"	sub1 {\n"
 		"		include = value\n"
@@ -608,7 +616,33 @@ START_TEST(test_load_files)
 		"		}\n"
 		"	}\n"
 		"}");
+	char *val1, *val2, *val3;
+
+	create_settings(contents);
+
+	val1 = settings->get_str(settings, "main.key1", NULL);
+	val2 = settings->get_str(settings, "main.sub1.key2", NULL);
+	/* loading the same file twice should not change anything, with... */
+	ck_assert(settings->load_files(settings, path, TRUE));
+	ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
+	ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
+	/* ...or without merging */
+	ck_assert(settings->load_files(settings, path, FALSE));
+	ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
+	ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
+
+	val1 = settings->get_str(settings, "main.key2", NULL);
+	val2 = settings->get_str(settings, "main.key3", NULL);
+	val3 = settings->get_str(settings, "main.none", NULL);
+	/* only pointers for modified settings should change, but still be valid */
+	ck_assert(settings->load_files(settings, include1, FALSE));
+	ck_assert(val1 != settings->get_str(settings, "main.key2", NULL));
+	ck_assert_str_eq(val1, "val2");
+	ck_assert(val2 == settings->get_str(settings, "main.key3", NULL));
+	ck_assert(val3 != settings->get_str(settings, "main.none", NULL));
+	ck_assert_str_eq(val3, "x");
 
+	settings->destroy(settings);
 	create_settings(contents);
 
 	ck_assert(settings->load_files(settings, include1, TRUE));
@@ -641,15 +675,20 @@ START_TEST(test_load_files_section)
 	ck_assert(settings->load_files_section(settings, include2, TRUE, "main.sub1"));
 	verify_include();
 
-	/* non existing files are no failure */
-	ck_assert(settings->load_files_section(settings, include1".conf", TRUE, ""));
+	/* non existing files are a failure here */
+	ck_assert(!settings->load_files_section(settings, include1".conf", TRUE, ""));
 	verify_include();
 
-	/* unreadable files are */
-	ck_assert(chunk_write(contents, include1".no", 0444, TRUE));
-	ck_assert(!settings->load_files_section(settings, include1".no", TRUE, ""));
-	unlink(include1".no");
-	verify_include();
+#ifndef WIN32
+	/* unreadable files are too (only fails when not running as root) */
+	if (getuid() != 0)
+	{
+		ck_assert(chunk_write(contents, include1".no", 0444, TRUE));
+		ck_assert(!settings->load_files_section(settings, include1".no", TRUE, ""));
+		unlink(include1".no");
+		verify_include();
+	}
+#endif
 
 	ck_assert(settings->load_files_section(settings, include2, FALSE, "main"));
 	verify_null("main.key1");
@@ -664,6 +703,87 @@ START_TEST(test_load_files_section)
 }
 END_TEST
 
+START_TEST(test_order_kv)
+{
+	chunk_t base = chunk_from_str(
+		"main {\n"
+		"	key1 = val1\n"
+		"	key2 = val2\n"
+		"	key3 = val3\n"
+		"}");
+	chunk_t include = chunk_from_str(
+		"main {\n"
+		"	key0 = val0\n"
+		"	key3 = val3\n"
+		"	key1 = val1\n"
+		"}");
+	linked_list_t *keys, *values;
+
+	create_settings(base);
+	ck_assert(chunk_write(include, include1, 0022, TRUE));
+
+	keys = linked_list_create_with_items("key1", "key2", "key3", NULL);
+	values = linked_list_create_with_items("val1", "val2", "val3", NULL);
+	verify_key_values(keys, values, "main");
+
+	/* the original order is maintained if the settings are merged */
+	ck_assert(settings->load_files(settings, include1, TRUE));
+	keys = linked_list_create_with_items("key1", "key2", "key3", "key0", NULL);
+	values = linked_list_create_with_items("val1", "val2", "val3", "val0", NULL);
+	verify_key_values(keys, values, "main");
+
+	/* but the new order is adopted if the settings are replaced */
+	ck_assert(settings->load_files(settings, include1, FALSE));
+	keys = linked_list_create_with_items("key0", "key3", "key1", NULL);
+	values = linked_list_create_with_items("val0", "val3", "val1", NULL);
+	verify_key_values(keys, values, "main");
+
+	unlink(include1);
+}
+END_TEST
+
+START_TEST(test_order_section)
+{
+	chunk_t base = chunk_from_str(
+		"main {\n"
+		"	sub1 {\n"
+		"	}\n"
+		"	sub2 {\n"
+		"	}\n"
+		"	sub3 {\n"
+		"	}\n"
+		"}");
+	chunk_t include = chunk_from_str(
+		"main {\n"
+		"	sub0 {\n"
+		"	}\n"
+		"	sub3 {\n"
+		"	}\n"
+		"	sub1 {\n"
+		"	}\n"
+		"}");
+	linked_list_t *sections;
+
+	create_settings(base);
+	ck_assert(chunk_write(include, include1, 0022, TRUE));
+
+	sections = linked_list_create_with_items("sub1", "sub2", "sub3", NULL);
+	verify_sections(sections, "main");
+
+	/* the original order is maintained if the settings are merged */
+	ck_assert(settings->load_files(settings, include1, TRUE));
+	sections = linked_list_create_with_items("sub1", "sub2", "sub3", "sub0", NULL);
+	verify_sections(sections, "main");
+
+	/* but the new order is adopted if the settings are replaced */
+	ck_assert(settings->load_files(settings, include1, FALSE));
+	sections = linked_list_create_with_items("sub0", "sub3", "sub1", NULL);
+	verify_sections(sections, "main");
+
+	unlink(include1);
+}
+END_TEST
+
 START_SETUP(setup_fallback_config)
 {
 	create_settings(chunk_from_str(
@@ -781,57 +901,85 @@ START_TEST(test_add_fallback_printf)
 }
 END_TEST
 
-START_SETUP(setup_invalid_config)
+START_SETUP(setup_string_config)
 {
 	create_settings(chunk_from_str(
-		"# section without name\n"
-		"{\n"
-		"	key1 = val1\n"
-		"}\n"
-		"main {\n"
-		"	key2 = val2\n"
-		"   # value without key\n"
-		"	= val3\n"
-		"	key4 = val4\n"
-		"	# key without value does not change it\n"
-		"	key4\n"
-		"	# subsection without name\n"
-		"	{\n"
-		"		key5 = val5\n"
-		"	}\n"
-		"	# empty include pattern\n"
-		"	include\n"
-		"	key6 = val6\n"
-		"}"));
+		"string = \"  with    accurate\twhitespace\"\n"
+		"special = \"all { special } characters # can be used.\"\n"
+		"unterminated = \"is fine\n"
+		"but = produces a warning\n"
+		"newlines = \"can either be encoded\\nor\\\n"
+		"escaped\"\n"
+		"quotes = \"\\\"and\\\" slashes \\\\ can \\\\ be\" # escaped too\n"
+		"multiple = \"strings\" are \"combined\"\n"
+		));
 }
 END_SETUP
 
-START_TEST(test_invalid)
+START_TEST(test_strings)
+{
+	verify_string("  with    accurate\twhitespace", "string");
+	verify_string("all { special } characters # can be used.", "special");
+	verify_string("is fine", "unterminated");
+	verify_string("produces a warning", "but");
+	verify_string("can either be encoded\nor\nescaped", "newlines");
+	verify_string("\"and\" slashes \\ can \\ be", "quotes");
+	verify_string("strings are combined", "multiple");
+}
+END_TEST
+
+START_TEST(test_valid)
 {
-	linked_list_t *keys, *values;
 	chunk_t contents;
 
-	verify_null("key1");
-	verify_null(".key1");
-	verify_null("%s.key1", "");
-	verify_string("val2", "main.key2");
-	verify_string("val4", "main.key4");
-	verify_null("main..key5");
-	verify_string("val6", "main.key6");
+	contents = chunk_from_str(
+		"single = value");
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	ck_assert(settings->load_files(settings, path, FALSE));
+	verify_string("value", "single");
 
-	keys = linked_list_create_with_items("main", NULL);
-	verify_sections(keys, "");
+	contents = chunk_from_str(
+		"singleline { single = value }");
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	ck_assert(settings->load_files(settings, path, FALSE));
+	verify_string("value", "singleline.single");
 
-	keys = linked_list_create_with_items(NULL);
-	verify_sections(keys, "main");
+	contents = chunk_from_str(
+		"singleline { sub { sub1 = val1 } single = value }");
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	ck_assert(settings->load_files(settings, path, FALSE));
+	verify_string("val1", "singleline.sub.sub1");
 
-	keys = linked_list_create_with_items("key2", "key4", "key6", NULL);
-	values = linked_list_create_with_items("val2", "val4", "val6", NULL);
-	verify_key_values(keys, values, "main");
+	contents = chunk_from_str(
+		"newline\n { single = value }");
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	ck_assert(settings->load_files(settings, path, FALSE));
+	verify_string("value", "newline.single");
+
+	contents = chunk_from_str(
+		"section {\n"
+		"	include # without pattern produces a warning, but is fine\n"
+		"}\n");
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	ck_assert(settings->load_files(settings, path, FALSE));
+}
+END_TEST
+
+START_TEST(test_invalid)
+{
+	chunk_t contents;
+
+	contents = chunk_from_str(
+		"{\n"
+		"	no = section name\n"
+		"}\n");
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	ck_assert(!settings->load_files(settings, path, FALSE));
 
-	/* FIXME: we should probably fix this */
 	contents = chunk_from_str(
-		"requires = newline");
+		"no {\n"
+		"	= key name\n"
+		"}\n");
 	ck_assert(chunk_write(contents, path, 0022, TRUE));
 	ck_assert(!settings->load_files(settings, path, FALSE));
 
@@ -842,7 +990,12 @@ START_TEST(test_invalid)
 	ck_assert(!settings->load_files(settings, path, FALSE));
 
 	contents = chunk_from_str(
-		"singleline { not = valid }\n");
+		"spaces in name {}");
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	ck_assert(!settings->load_files(settings, path, FALSE));
+
+	contents = chunk_from_str(
+		"only = a single setting = per line");
 	ck_assert(chunk_write(contents, path, 0022, TRUE));
 	ck_assert(!settings->load_files(settings, path, FALSE));
 }
@@ -903,6 +1056,8 @@ Suite *settings_suite_create()
 	tcase_add_test(tc, test_include);
 	tcase_add_test(tc, test_load_files);
 	tcase_add_test(tc, test_load_files_section);
+	tcase_add_test(tc, test_order_kv);
+	tcase_add_test(tc, test_order_section);
 	suite_add_tcase(s, tc);
 
 	tc = tcase_create("fallback");
@@ -911,8 +1066,14 @@ Suite *settings_suite_create()
 	tcase_add_test(tc, test_add_fallback_printf);
 	suite_add_tcase(s, tc);
 
-	tc = tcase_create("invalid data");
-	tcase_add_checked_fixture(tc, setup_invalid_config, teardown_config);
+	tc = tcase_create("strings");
+	tcase_add_checked_fixture(tc, setup_string_config, teardown_config);
+	tcase_add_test(tc, test_strings);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("valid/invalid data");
+	tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
+	tcase_add_test(tc, test_valid);
 	tcase_add_test(tc, test_invalid);
 	suite_add_tcase(s, tc);
 
diff --git a/src/libstrongswan/tests/suites/test_stream.c b/src/libstrongswan/tests/suites/test_stream.c
index 2d3173d..899306a 100644
--- a/src/libstrongswan/tests/suites/test_stream.c
+++ b/src/libstrongswan/tests/suites/test_stream.c
@@ -18,7 +18,9 @@
 #include <unistd.h>
 
 static char* services[] = {
+#ifndef WIN32
 	"unix:///tmp/strongswan-test-service.sck",
+#endif
 	"tcp://127.0.0.1:7766",
 	"tcp://[::1]:7766",
 };
@@ -121,7 +123,6 @@ START_TEST(test_async)
 	stream_service_t *service;
 	stream_t *stream;
 
-
 	lib->processor->set_threads(lib->processor, 8);
 
 	service = lib->streams->create_service(lib->streams, services[_i], 1);
diff --git a/src/libstrongswan/tests/suites/test_threading.c b/src/libstrongswan/tests/suites/test_threading.c
index 844959e..0526d9d 100644
--- a/src/libstrongswan/tests/suites/test_threading.c
+++ b/src/libstrongswan/tests/suites/test_threading.c
@@ -16,7 +16,6 @@
 
 #include "test_suite.h"
 
-#include <sched.h>
 #include <unistd.h>
 
 #include <threading/thread.h>
@@ -1215,6 +1214,8 @@ static void *cleanup_cancel_run(void *data)
 {
 	thread_cancelability(FALSE);
 
+	barrier_wait(barrier);
+
 	thread_cleanup_push(cleanup3, data);
 	thread_cleanup_push(cleanup2, data);
 	thread_cleanup_push(cleanup1, data);
@@ -1234,11 +1235,13 @@ START_TEST(test_cleanup_cancel)
 	uintptr_t values[THREADS];
 	int i;
 
+	barrier = barrier_create(THREADS+1);
 	for (i = 0; i < THREADS; i++)
 	{
 		values[i] = 1;
 		threads[i] = thread_create(cleanup_cancel_run, &values[i]);
 	}
+	barrier_wait(barrier);
 	for (i = 0; i < THREADS; i++)
 	{
 		threads[i]->cancel(threads[i]);
@@ -1248,6 +1251,7 @@ START_TEST(test_cleanup_cancel)
 		threads[i]->join(threads[i]);
 		ck_assert_int_eq(values[i], 4);
 	}
+	barrier_destroy(barrier);
 }
 END_TEST
 
diff --git a/src/libstrongswan/tests/suites/test_utils.c b/src/libstrongswan/tests/suites/test_utils.c
index 0260726..abca462 100644
--- a/src/libstrongswan/tests/suites/test_utils.c
+++ b/src/libstrongswan/tests/suites/test_utils.c
@@ -508,34 +508,55 @@ START_TEST(test_strreplace)
 END_TEST
 
 /*******************************************************************************
- * path_dirname/basename
+ * path_dirname/basename/absolute
  */
 
 static struct {
 	char *path;
 	char *dir;
 	char *base;
+	bool absolute;
 } path_data[] = {
-	{NULL, ".", "."},
-	{"", ".", "."},
-	{".", ".", "."},
-	{"..", ".", ".."},
-	{"/", "/", "/"},
-	{"//", "/", "/"},
-	{"foo", ".", "foo"},
-	{"f/", ".", "f"},
-	{"foo/", ".", "foo"},
-	{"foo//", ".", "foo"},
-	{"/f", "/", "f"},
-	{"/f/", "/", "f"},
-	{"/foo", "/", "foo"},
-	{"/foo/", "/", "foo"},
-	{"//foo/", "/", "foo"},
-	{"foo/bar", "foo", "bar"},
-	{"foo//bar", "foo", "bar"},
-	{"/foo/bar", "/foo", "bar"},
-	{"/foo/bar/", "/foo", "bar"},
-	{"/foo/bar/baz", "/foo/bar", "baz"},
+	{NULL, ".", ".", FALSE},
+	{"", ".", ".", FALSE},
+	{".", ".", ".", FALSE},
+	{"..", ".", "..", FALSE},
+#ifdef WIN32
+	{"C:\\", "C:", "C:", TRUE},
+	{"X:\\\\", "X:", "X:", TRUE},
+	{"foo", ".", "foo", FALSE},
+	{"f\\", ".", "f", FALSE},
+	{"foo\\", ".", "foo", FALSE},
+	{"foo\\\\", ".", "foo", FALSE},
+	{"d:\\f", "d:", "f", TRUE},
+	{"C:\\f\\", "C:", "f", TRUE},
+	{"C:\\foo", "C:", "foo", TRUE},
+	{"C:\\foo\\", "C:", "foo", TRUE},
+	{"foo\\bar", "foo", "bar", FALSE},
+	{"foo\\\\bar", "foo", "bar", FALSE},
+	{"C:\\foo\\bar", "C:\\foo", "bar", TRUE},
+	{"C:\\foo\\bar\\", "C:\\foo", "bar", TRUE},
+	{"C:\\foo\\bar\\baz", "C:\\foo\\bar", "baz", TRUE},
+	{"\\foo\\bar", "\\foo", "bar", FALSE},
+	{"\\\\foo\\bar", "\\\\foo", "bar", TRUE},
+#else /* !WIN32 */
+	{"/", "/", "/", TRUE},
+	{"//", "/", "/", TRUE},
+	{"foo", ".", "foo", FALSE},
+	{"f/", ".", "f", FALSE},
+	{"foo/", ".", "foo", FALSE},
+	{"foo//", ".", "foo", FALSE},
+	{"/f", "/", "f", TRUE},
+	{"/f/", "/", "f", TRUE},
+	{"/foo", "/", "foo", TRUE},
+	{"/foo/", "/", "foo", TRUE},
+	{"//foo/", "/", "foo", TRUE},
+	{"foo/bar", "foo", "bar", FALSE},
+	{"foo//bar", "foo", "bar", FALSE},
+	{"/foo/bar", "/foo", "bar", TRUE},
+	{"/foo/bar/", "/foo", "bar", TRUE},
+	{"/foo/bar/baz", "/foo/bar", "baz", TRUE},
+#endif
 };
 
 START_TEST(test_path_dirname)
@@ -558,6 +579,12 @@ START_TEST(test_path_basename)
 }
 END_TEST
 
+START_TEST(test_path_absolute)
+{
+	ck_assert(path_data[_i].absolute == path_absolute(path_data[_i].path));
+}
+END_TEST
+
 /*******************************************************************************
  * time_printf_hook
  */
@@ -674,7 +701,11 @@ Suite *utils_suite_create()
 	TCase *tc;
 
 	/* force a timezone to match non-UTC conversions */
+#ifdef WIN32
+	_putenv("TZ=GST-1GDT");
+#else
 	setenv("TZ", "Europe/Zurich", 1);
+#endif
 	tzset();
 
 	s = suite_create("utils");
@@ -725,11 +756,18 @@ Suite *utils_suite_create()
 	tcase_add_loop_test(tc, test_strreplace, 0, countof(strreplace_data));
 	suite_add_tcase(s, tc);
 
-	tc = tcase_create("path_dirname/basename");
+	tc = tcase_create("path_dirname");
 	tcase_add_loop_test(tc, test_path_dirname, 0, countof(path_data));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("path_basename");
 	tcase_add_loop_test(tc, test_path_basename, 0, countof(path_data));
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("path_absolute");
+	tcase_add_loop_test(tc, test_path_absolute, 0, countof(path_data));
+	suite_add_tcase(s, tc);
+
 	tc = tcase_create("printf_hooks");
 	tcase_add_loop_test(tc, test_time_printf_hook, 0, countof(time_data));
 	tcase_add_loop_test(tc, test_time_delta_printf_hook, 0, countof(time_delta_data));
diff --git a/src/libstrongswan/tests/suites/test_watcher.c b/src/libstrongswan/tests/suites/test_watcher.c
index 9415bea..11b4c3a 100644
--- a/src/libstrongswan/tests/suites/test_watcher.c
+++ b/src/libstrongswan/tests/suites/test_watcher.c
@@ -17,7 +17,6 @@
 
 #include <library.h>
 
-#include <sched.h>
 #include <unistd.h>
 #include <errno.h>
 
@@ -48,7 +47,7 @@ START_TEST(test_read)
 
 	for (c = 'a'; c <= 'z'; c++)
 	{
-		ck_assert_int_eq(write(fd[1], &c, 1), 1);
+		ck_assert_int_eq(send(fd[1], &c, 1, 0), 1);
 		while (testbuf[0] != c)
 		{
 			sched_yield();
@@ -84,7 +83,7 @@ START_TEST(test_write)
 
 	lib->watcher->add(lib->watcher, fd[1], WATCHER_WRITE, writecb, &in);
 
-	ck_assert_int_eq(read(fd[0], &out, 1), 1);
+	ck_assert_int_eq(recv(fd[0], &out, 1, 0), 1);
 	ck_assert_int_eq(out, in);
 
 	lib->watcher->remove(lib->watcher, fd[1]);
@@ -123,7 +122,7 @@ START_TEST(test_multiread)
 	{
 		for (in = 'a'; in <= 'z'; in++)
 		{
-			ck_assert_int_eq(write(fd[i][1], &in, 1), 1);
+			ck_assert_int_eq(send(fd[i][1], &in, 1, 0), 1);
 			while (out[i] != in)
 			{
 				sched_yield();
@@ -171,7 +170,7 @@ START_TEST(test_multiwrite)
 	{
 		for (i = 0; i < countof(fd); i++)
 		{
-			ck_assert_int_eq(read(fd[i][0], &out, 1), 1);
+			ck_assert_int_eq(recv(fd[i][0], &out, 1, 0), 1);
 			ck_assert_int_eq(out, i);
 		}
 	}
diff --git a/src/libstrongswan/tests/test_runner.c b/src/libstrongswan/tests/test_runner.c
index 5ec4198..8f2e985 100644
--- a/src/libstrongswan/tests/test_runner.c
+++ b/src/libstrongswan/tests/test_runner.c
@@ -18,6 +18,7 @@
 #include "test_runner.h"
 
 #include <library.h>
+#include <threading/thread.h>
 #include <plugins/plugin_feature.h>
 #include <collections/array.h>
 #include <utils/test.h>
@@ -26,6 +27,7 @@
 #include <dirent.h>
 #include <unistd.h>
 #include <limits.h>
+#include <stdlib.h>
 
 /**
  * Get a tty color escape character for stderr
@@ -33,32 +35,12 @@
 #define TTY(color) tty_escape_get(2, TTY_FG_##color)
 
 /**
- * Initialize the lookup table for testable functions (defined in
- * libstrongswan).  We don't use the constructor attribute as the order can't
- * really be defined (clang does not support it and gcc does not adhere to it in
- * the monolithic build).  The function here is a weak symbol in libstrongswan.
+ * A global symbol indicating libtest linkage
  */
-void testable_functions_create()
-{
-	if (!testable_functions)
-	{
-		testable_functions = hashtable_create(hashtable_hash_str,
-											  hashtable_equals_str, 8);
-	}
-}
-
-/**
- * Destroy the lookup table for testable functions
- */
-static void testable_functions_destroy() __attribute__ ((destructor));
-static void testable_functions_destroy()
-{
-	DESTROY_IF(testable_functions);
-	/* if leak detective is enabled plugins are not actually unloaded, which
-	 * means their destructor is called AFTER this one when the process
-	 * terminates, make sure this does not crash */
-	testable_functions = NULL;
-}
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+bool test_runner_available = TRUE;
 
 /**
  * Destroy a single test suite and associated data
@@ -114,13 +96,13 @@ static void filter_suites(array_t *loaded)
  * Load all available test suites, or optionally only selected ones.
  */
 static array_t *load_suites(test_configuration_t configs[],
-							test_runner_init_t init)
+							test_runner_init_t init, char *cfg)
 {
 	array_t *suites;
 	bool old = FALSE;
 	int i;
 
-	library_init(NULL, "test-runner");
+	library_init(cfg, "test-runner");
 
 	test_setup_handler();
 
@@ -205,11 +187,17 @@ static bool call_fixture(test_case_t *tcase, bool up)
 		{
 			if (up)
 			{
-				fixture->setup();
+				if (fixture->setup)
+				{
+					fixture->setup();
+				}
 			}
 			else
 			{
-				fixture->teardown();
+				if (fixture->teardown)
+				{
+					fixture->teardown();
+				}
 			}
 		}
 		else
@@ -226,12 +214,12 @@ static bool call_fixture(test_case_t *tcase, bool up)
 /**
  * Test initialization, initializes libstrongswan for the next run
  */
-static bool pre_test(test_runner_init_t init)
+static bool pre_test(test_runner_init_t init, char *cfg)
 {
 	level_t level = LEVEL_SILENT;
 	char *verbosity;
 
-	library_init(NULL, "test-runner");
+	library_init(cfg, "test-runner");
 
 	/* use non-blocking RNG to generate keys fast */
 	lib->settings->set_default_str(lib->settings,
@@ -371,6 +359,7 @@ static void print_failures(array_t *failures)
 {
 	failure_t failure;
 
+	threads_init();
 	backtrace_init();
 
 	while (array_remove(failures, 0, &failure))
@@ -390,12 +379,13 @@ static void print_failures(array_t *failures)
 	}
 
 	backtrace_deinit();
+	threads_deinit();
 }
 
 /**
  * Run a single test case with fixtures
  */
-static bool run_case(test_case_t *tcase, test_runner_init_t init)
+static bool run_case(test_case_t *tcase, test_runner_init_t init, char *cfg)
 {
 	enumerator_t *enumerator;
 	test_function_t *tfun;
@@ -414,7 +404,7 @@ static bool run_case(test_case_t *tcase, test_runner_init_t init)
 
 		for (i = tfun->start; i < tfun->end; i++)
 		{
-			if (pre_test(init))
+			if (pre_test(init, cfg))
 			{
 				bool ok = FALSE;
 				int leaks = 0;
@@ -483,7 +473,7 @@ static bool run_case(test_case_t *tcase, test_runner_init_t init)
 /**
  * Run a single test suite
  */
-static bool run_suite(test_suite_t *suite, test_runner_init_t init)
+static bool run_suite(test_suite_t *suite, test_runner_init_t init, char *cfg)
 {
 	enumerator_t *enumerator;
 	test_case_t *tcase;
@@ -494,7 +484,7 @@ static bool run_suite(test_suite_t *suite, test_runner_init_t init)
 	enumerator = array_create_enumerator(suite->tcases);
 	while (enumerator->enumerate(enumerator, &tcase))
 	{
-		if (run_case(tcase, init))
+		if (run_case(tcase, init, cfg))
 		{
 			passed++;
 		}
@@ -522,11 +512,14 @@ int test_runner_run(const char *name, test_configuration_t configs[],
 	test_suite_t *suite;
 	enumerator_t *enumerator;
 	int passed = 0, result;
+	char *cfg;
 
 	/* redirect all output to stderr (to redirect make's stdout to /dev/null) */
 	dup2(2, 1);
 
-	suites = load_suites(configs, init);
+	cfg = getenv("TESTS_STRONGSWAN_CONF");
+
+	suites = load_suites(configs, init, cfg);
 	if (!suites)
 	{
 		return EXIT_FAILURE;
@@ -537,7 +530,7 @@ int test_runner_run(const char *name, test_configuration_t configs[],
 	enumerator = array_create_enumerator(suites);
 	while (enumerator->enumerate(enumerator, &suite))
 	{
-		if (run_suite(suite, init))
+		if (run_suite(suite, init, cfg))
 		{
 			passed++;
 		}
diff --git a/src/libstrongswan/tests/test_runner.h b/src/libstrongswan/tests/test_runner.h
index 643b622..de87a1f 100644
--- a/src/libstrongswan/tests/test_runner.h
+++ b/src/libstrongswan/tests/test_runner.h
@@ -64,7 +64,13 @@ struct test_configuration_t {
 /**
  * Run test configuration.
  *
- * The configs array must be terminated with a NULL element.
+ * The configs array must be terminated with a NULL element. The following
+ * environment variables are currently supported:
+ *
+ * - TESTS_VERBOSITY: Numerical loglevel for debug log
+ * - TESTS_STRONGSWAN_CONF: Specify a path to a custom strongswan.conf
+ * - TESTS_SUITES: Run specific test suites only
+ * - TESTS_REDUCED_KEYLENGTHS: Test minimal keylengths for public key tests only
  *
  * @param name			name of test runner
  * @param config		test suite constructors with dependencies
diff --git a/src/libstrongswan/tests/test_suite.c b/src/libstrongswan/tests/test_suite.c
index fb40b05..00ac318 100644
--- a/src/libstrongswan/tests/test_suite.c
+++ b/src/libstrongswan/tests/test_suite.c
@@ -18,7 +18,11 @@
 #include <signal.h>
 #include <unistd.h>
 
+#ifndef WIN32
 #include <pthread.h>
+#endif
+
+#include <threading/thread.h>
 
 /**
  * Failure message buf
@@ -41,9 +45,9 @@ static int failure_line;
 static backtrace_t *failure_backtrace;
 
 /**
- * Longjump restore point when failing
+ * Flag to indicate if a worker thread failed
  */
-sigjmp_buf test_restore_point_env;
+static bool worker_failed;
 
 /**
  * See header.
@@ -119,54 +123,200 @@ void test_suite_add_case(test_suite_t *suite, test_case_t *tcase)
 	array_insert(suite->tcases, -1, tcase);
 }
 
+#ifdef WIN32
+
 /**
- * Main thread performing tests
+ * Longjump restore point when failing
  */
-static pthread_t main_thread;
+jmp_buf test_restore_point_env;
+
+/**
+ * Thread ID of main thread
+ */
+static DWORD main_thread;
+
+/**
+ * APC routine invoked by main thread on worker failure
+ */
+static void WINAPI set_worker_failure(ULONG_PTR dwParam)
+{
+	worker_failed = TRUE;
+}
 
 /**
  * Let test case fail
  */
-static inline void test_failure()
+static void test_failure()
 {
-	if (pthread_self() == main_thread)
+	if (GetCurrentThreadId() == main_thread)
 	{
-		siglongjmp(test_restore_point_env, 1);
+		longjmp(test_restore_point_env, 1);
 	}
 	else
 	{
-		pthread_kill(main_thread, SIGUSR1);
-		/* terminate thread to prevent it from going wild */
-		pthread_exit(NULL);
+		HANDLE *thread;
+
+		thread = OpenThread(THREAD_SET_CONTEXT, FALSE, main_thread);
+		if (thread)
+		{
+			QueueUserAPC(set_worker_failure, thread, (uintptr_t)NULL);
+			CloseHandle(thread);
+		}
+		thread_exit(NULL);
 	}
 }
 
 /**
  * See header.
  */
-void test_fail_vmsg(const char *file, int line, char *fmt, va_list args)
+void test_fail_if_worker_failed()
 {
-	vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
-	failure_line = line;
-	failure_file = file;
+	if (GetCurrentThreadId() == main_thread && worker_failed)
+	{
+		test_failure();
+	}
+}
 
-	test_failure();
+/**
+ * Vectored exception handler
+ */
+static long WINAPI eh_handler(PEXCEPTION_POINTERS ei)
+{
+	char *ename;
+	bool old = FALSE;
+
+	switch (ei->ExceptionRecord->ExceptionCode)
+	{
+		case EXCEPTION_ACCESS_VIOLATION:
+			ename = "ACCESS_VIOLATION";
+			break;
+		case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+			ename = "ARRAY_BOUNDS_EXCEEDED";
+			break;
+		case EXCEPTION_DATATYPE_MISALIGNMENT:
+			ename = "DATATYPE_MISALIGNMENT";
+			break;
+		case EXCEPTION_FLT_DENORMAL_OPERAND:
+			ename = "FLT_DENORMAL_OPERAND";
+			break;
+		case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+			ename = "FLT_DIVIDE_BY_ZERO";
+			break;
+		case EXCEPTION_FLT_INEXACT_RESULT:
+			ename = "FLT_INEXACT_RESULT";
+			break;
+		case EXCEPTION_FLT_INVALID_OPERATION:
+			ename = "FLT_INVALID_OPERATION";
+			break;
+		case EXCEPTION_FLT_OVERFLOW:
+			ename = "FLT_OVERFLOW";
+			break;
+		case EXCEPTION_FLT_STACK_CHECK:
+			ename = "FLT_STACK_CHECK";
+			break;
+		case EXCEPTION_FLT_UNDERFLOW:
+			ename = "FLT_UNDERFLOW";
+			break;
+		case EXCEPTION_ILLEGAL_INSTRUCTION:
+			ename = "ILLEGAL_INSTRUCTION";
+			break;
+		case EXCEPTION_IN_PAGE_ERROR:
+			ename = "IN_PAGE_ERROR";
+			break;
+		case EXCEPTION_INT_DIVIDE_BY_ZERO:
+			ename = "INT_DIVIDE_BY_ZERO";
+			break;
+		case EXCEPTION_INT_OVERFLOW:
+			ename = "INT_OVERFLOW";
+			break;
+		case EXCEPTION_INVALID_DISPOSITION:
+			ename = "INVALID_DISPOSITION";
+			break;
+		case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+			ename = "NONCONTINUABLE_EXCEPTION";
+			break;
+		case EXCEPTION_PRIV_INSTRUCTION:
+			ename = "PRIV_INSTRUCTION";
+			break;
+		case EXCEPTION_STACK_OVERFLOW:
+			ename = "STACK_OVERFLOW";
+			break;
+		default:
+			return EXCEPTION_CONTINUE_EXECUTION;
+	}
+
+	if (lib->leak_detective)
+	{
+		old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
+	}
+	failure_backtrace = backtrace_create(5);
+	if (lib->leak_detective)
+	{
+		lib->leak_detective->set_state(lib->leak_detective, old);
+	}
+	failure_line = 0;
+	test_fail_msg(NULL, 0, "%s exception", ename);
+	/* not reached */
+	return EXCEPTION_CONTINUE_EXECUTION;
 }
 
 /**
  * See header.
  */
-void test_fail_msg(const char *file, int line, char *fmt, ...)
+void test_setup_handler()
 {
-	va_list args;
+	main_thread = GetCurrentThreadId();
+	AddVectoredExceptionHandler(0, eh_handler);
+}
 
-	va_start(args, fmt);
-	vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
-	failure_line = line;
-	failure_file = file;
-	va_end(args);
+/**
+ * See header.
+ */
+void test_setup_timeout(int s)
+{
+	/* TODO: currently not supported. SetTimer()? */
 
-	test_failure();
+	worker_failed = FALSE;
+}
+
+#else /* !WIN32 */
+
+/**
+ * Longjump restore point when failing
+ */
+sigjmp_buf test_restore_point_env;
+
+/**
+ * Main thread performing tests
+ */
+static pthread_t main_thread;
+
+/**
+ * Let test case fail
+ */
+static inline void test_failure()
+{
+	if (pthread_self() == main_thread)
+	{
+		siglongjmp(test_restore_point_env, 1);
+	}
+	else
+	{
+		pthread_kill(main_thread, SIGUSR1);
+		/* terminate thread to prevent it from going wild */
+		pthread_exit(NULL);
+	}
+}
+
+/**
+ * See header.
+ */
+void test_fail_if_worker_failed()
+{
+	if (pthread_self() == main_thread && worker_failed)
+	{
+		test_failure();
+	}
 }
 
 /**
@@ -180,8 +330,9 @@ static void test_sighandler(int signal)
 	switch (signal)
 	{
 		case SIGUSR1:
-			/* a different thread failed, abort test */
-			return test_failure();
+			/* a different thread failed, abort test at the next opportunity */
+			worker_failed = TRUE;
+			return;
 		case SIGSEGV:
 			signame = "SIGSEGV";
 			break;
@@ -251,6 +402,37 @@ void test_setup_timeout(int s)
 	sigaction(SIGUSR1, &action, NULL);
 
 	alarm(s);
+
+	worker_failed = FALSE;
+}
+
+#endif /* !WIN32 */
+
+/**
+ * See header.
+ */
+void test_fail_vmsg(const char *file, int line, char *fmt, va_list args)
+{
+	vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
+	failure_line = line;
+	failure_file = file;
+
+	test_failure();
+}
+/**
+ * See header.
+ */
+void test_fail_msg(const char *file, int line, char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vsnprintf(failure_buf, sizeof(failure_buf), fmt, args);
+	failure_line = line;
+	failure_file = file;
+	va_end(args);
+
+	test_failure();
 }
 
 /**
diff --git a/src/libstrongswan/tests/test_suite.h b/src/libstrongswan/tests/test_suite.h
index c44f149..da57ab4 100644
--- a/src/libstrongswan/tests/test_suite.h
+++ b/src/libstrongswan/tests/test_suite.h
@@ -174,7 +174,11 @@ void test_suite_add_case(test_suite_t *suite, test_case_t *tcase);
 /**
  * sigjmp restore point used by test_restore_point
  */
+#ifdef WIN32
+extern jmp_buf test_restore_point_env;
+#else
 extern sigjmp_buf test_restore_point_env;
+#endif
 
 /**
  * Set or return from an execution restore point
@@ -185,7 +189,11 @@ extern sigjmp_buf test_restore_point_env;
  *
  * @return			TRUE if restore point set, FALSE when restored
  */
-#define test_restore_point() (sigsetjmp(test_restore_point_env, 1) == 0)
+#ifdef WIN32
+# define test_restore_point() (setjmp(test_restore_point_env) == 0)
+#else
+# define test_restore_point() (sigsetjmp(test_restore_point_env, 1) == 0)
+#endif
 
 /**
  * Set up signal handlers for test cases
@@ -237,6 +245,12 @@ void test_fail_vmsg(const char *file, int line, char *fmt, va_list args);
 void test_fail_msg(const char *file, int line, char *fmt, ...);
 
 /**
+ * Let a test fail if one of the worker threads has failed (only if called from
+ * the main thread).
+ */
+void test_fail_if_worker_failed();
+
+/**
  * Check if two integers equal, fail test if not
  *
  * @param a			first integer
@@ -246,6 +260,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 ({ \
 	typeof(a) _a = a; \
 	typeof(b) _b = b; \
+	test_fail_if_worker_failed(); \
 	if (_a != _b) \
 	{ \
 		test_fail_msg(__FILE__, __LINE__, #a " != " #b " (%d != %d)", _a, _b); \
@@ -262,6 +277,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 ({ \
 	char* _a = (char*)a; \
 	char* _b = (char*)b; \
+	test_fail_if_worker_failed(); \
 	if (!_a || !_b || !streq(_a, _b)) \
 	{ \
 		test_fail_msg(__FILE__, __LINE__, \
@@ -270,12 +286,31 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 })
 
 /**
+ * Check if two chunks are equal, fail test if not
+ *
+ * @param a			first chunk
+ * @param b			second chunk
+ */
+#define test_chunk_eq(a, b) \
+({ \
+	chunk_t _a = (chunk_t)a; \
+	chunk_t _b = (chunk_t)b; \
+	test_fail_if_worker_failed(); \
+	if (_a.len != _b.len || !memeq(a.ptr, b.ptr, a.len)) \
+	{ \
+		test_fail_msg(__FILE__, __LINE__, \
+					  #a " != " #b " (\"%#B\" != \"%#B\")", &_a, &_b); \
+	} \
+})
+
+/**
  * Check if a statement evaluates to TRUE, fail test if not
  *
  * @param x			statement to evaluate
  */
 #define test_assert(x) \
 ({ \
+	test_fail_if_worker_failed(); \
 	if (!(x)) \
 	{ \
 		test_fail_msg(__FILE__, __LINE__, #x); \
@@ -291,6 +326,7 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
  */
 #define test_assert_msg(x, fmt, ...) \
 ({ \
+	test_fail_if_worker_failed(); \
 	if (!(x)) \
 	{ \
 		test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
@@ -306,9 +342,11 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 #define ck_assert test_assert
 #define ck_assert_msg test_assert_msg
 #define ck_assert_str_eq test_str_eq
+#define ck_assert_chunk_eq test_chunk_eq
 #define fail(fmt, ...) test_fail_msg(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
 #define fail_if(x, fmt, ...) \
 ({ \
+	test_fail_if_worker_failed(); \
 	if (x) \
 	{ \
 		test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
@@ -323,10 +361,10 @@ void test_fail_msg(const char *file, int line, char *fmt, ...);
 #define tcase_set_timeout test_case_set_timeout
 #define suite_add_tcase test_suite_add_case
 #define START_TEST(name) static void name (int _i) {
-#define END_TEST }
+#define END_TEST test_fail_if_worker_failed(); }
 #define START_SETUP(name) static void name() {
-#define END_SETUP }
+#define END_SETUP test_fail_if_worker_failed(); }
 #define START_TEARDOWN(name) static void name() {
-#define END_TEARDOWN }
+#define END_TEARDOWN test_fail_if_worker_failed(); }
 
 #endif /** TEST_SUITE_H_ @}*/
diff --git a/src/libstrongswan/tests/tests.c b/src/libstrongswan/tests/tests.c
index 9f2adfd..d95ddd9 100644
--- a/src/libstrongswan/tests/tests.c
+++ b/src/libstrongswan/tests/tests.c
@@ -35,8 +35,14 @@ static bool test_runner_init(bool init)
 {
 	if (init)
 	{
-		plugin_loader_add_plugindirs(PLUGINDIR, PLUGINS);
-		if (!lib->plugins->load(lib->plugins, PLUGINS))
+		char *plugins, *plugindir;
+
+		plugins = lib->settings->get_str(lib->settings,
+										"tests.load", PLUGINS);
+		plugindir = lib->settings->get_str(lib->settings,
+										"tests.plugindir", PLUGINDIR);
+		plugin_loader_add_plugindirs(plugindir, plugins);
+		if (!lib->plugins->load(lib->plugins, plugins))
 		{
 			return FALSE;
 		}
diff --git a/src/libstrongswan/tests/tests.h b/src/libstrongswan/tests/tests.h
index 82a5137..ab0f642 100644
--- a/src/libstrongswan/tests/tests.h
+++ b/src/libstrongswan/tests/tests.h
@@ -35,6 +35,7 @@ TEST_SUITE(host_suite_create)
 TEST_SUITE(printf_suite_create)
 TEST_SUITE(hasher_suite_create)
 TEST_SUITE(crypter_suite_create)
+TEST_SUITE(crypto_factory_suite_create)
 TEST_SUITE(pen_suite_create)
 TEST_SUITE(asn1_suite_create)
 TEST_SUITE(asn1_parser_suite_create)
diff --git a/src/libstrongswan/threading/thread.c b/src/libstrongswan/threading/thread.c
index 0adfb31..593f44a 100644
--- a/src/libstrongswan/threading/thread.c
+++ b/src/libstrongswan/threading/thread.c
@@ -301,6 +301,9 @@ static void *thread_main(private_thread_t *this)
 #ifdef HAVE_GETTID
 	DBG2(DBG_LIB, "created thread %.2d [%u]",
 		 this->id, gettid());
+#elif defined(WIN32)
+	DBG2(DBG_LIB, "created thread %.2d [%p]",
+		 this->id, this->thread_id.p);
 #else
 	DBG2(DBG_LIB, "created thread %.2d [%lx]",
 		 this->id, (u_long)this->thread_id);
diff --git a/src/libstrongswan/threading/windows/mutex.c b/src/libstrongswan/threading/windows/mutex.c
new file mode 100644
index 0000000..a268895
--- /dev/null
+++ b/src/libstrongswan/threading/windows/mutex.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 "thread.h"
+
+#include <utils/debug.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+
+typedef struct private_mutex_t private_mutex_t;
+typedef struct private_condvar_t private_condvar_t;
+
+/**
+ * private data of mutex
+ */
+struct private_mutex_t {
+
+	/**
+	 * public functions
+	 */
+	mutex_t public;
+
+	/**
+	 * wrapped critical section
+	 */
+	CRITICAL_SECTION cs;
+
+	/**
+	 * Recursive lock count
+	 */
+	u_int times;
+};
+
+/**
+ * private data of condvar
+ */
+struct private_condvar_t {
+
+	/**
+	 * public functions
+	 */
+	condvar_t public;
+
+	/**
+	 * wrapped condition variable
+	 */
+	CONDITION_VARIABLE cv;
+};
+
+
+METHOD(mutex_t, lock, void,
+	private_mutex_t *this)
+{
+	EnterCriticalSection(&this->cs);
+	this->times++;
+}
+
+METHOD(mutex_t, unlock, void,
+	private_mutex_t *this)
+{
+	this->times--;
+	LeaveCriticalSection(&this->cs);
+}
+
+METHOD(mutex_t, mutex_destroy, void,
+	private_mutex_t *this)
+{
+	DeleteCriticalSection(&this->cs);
+	free(this);
+}
+
+/*
+ * see header file
+ */
+mutex_t *mutex_create(mutex_type_t type)
+{
+	private_mutex_t *this;
+
+	INIT(this,
+		.public = {
+			.lock = _lock,
+			.unlock = _unlock,
+			.destroy = _mutex_destroy,
+		},
+	);
+
+	/* CriticalSections are recursive, we use it for all mutex types. */
+	InitializeCriticalSection(&this->cs);
+
+	return &this->public;
+}
+
+METHOD(condvar_t, timed_wait, bool,
+	private_condvar_t *this, mutex_t *pubmutex, u_int timeout)
+{
+	private_mutex_t *mutex = (private_mutex_t*)pubmutex;
+	u_int times;
+	bool ret;
+
+	thread_set_active_condvar(&this->cv);
+
+	/* while a CriticalSection is recursive, waiting in a condvar releases
+	 * only one mutex. So release (and reaquire) all locks except the last. */
+	times = mutex->times;
+	while (mutex->times-- > 1)
+	{
+		LeaveCriticalSection(&mutex->cs);
+	}
+
+	ret = SleepConditionVariableCS(&this->cv, &mutex->cs, timeout);
+
+	while (++mutex->times < times)
+	{
+		EnterCriticalSection(&mutex->cs);
+	}
+
+	thread_set_active_condvar(NULL);
+
+	return ret == 0;
+}
+
+METHOD(condvar_t, wait_, void,
+	private_condvar_t *this, mutex_t *mutex)
+{
+	timed_wait(this, mutex, INFINITE);
+}
+
+METHOD(condvar_t, timed_wait_abs, bool,
+	private_condvar_t *this, mutex_t *mutex, timeval_t tv)
+{
+	DWORD timeout;
+	timeval_t now, diff;
+
+	time_monotonic(&now);
+	if (timercmp(&now, &tv, >))
+	{
+		return TRUE;
+	}
+	timersub(&tv, &now, &diff);
+	timeout = diff.tv_sec * 1000 + diff.tv_usec / 1000;
+
+	return timed_wait(this, mutex, timeout);
+}
+
+METHOD(condvar_t, signal_, void,
+	private_condvar_t *this)
+{
+	WakeConditionVariable(&this->cv);
+}
+
+METHOD(condvar_t, broadcast, void,
+	private_condvar_t *this)
+{
+	WakeAllConditionVariable(&this->cv);
+}
+
+METHOD(condvar_t, condvar_destroy, void,
+	private_condvar_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+condvar_t *condvar_create(condvar_type_t type)
+{
+	private_condvar_t *this;
+
+	INIT(this,
+		.public = {
+			.wait = _wait_,
+			.timed_wait = _timed_wait,
+			.timed_wait_abs = _timed_wait_abs,
+			.signal = _signal_,
+			.broadcast = _broadcast,
+			.destroy = _condvar_destroy,
+		}
+	);
+
+	InitializeConditionVariable(&this->cv);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/threading/windows/rwlock.c b/src/libstrongswan/threading/windows/rwlock.c
new file mode 100644
index 0000000..0de57f7
--- /dev/null
+++ b/src/libstrongswan/threading/windows/rwlock.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 "thread.h"
+
+#include <utils/debug.h>
+#include <threading/rwlock.h>
+#include <threading/rwlock_condvar.h>
+#include <threading/thread_value.h>
+
+typedef struct private_rwlock_t private_rwlock_t;
+typedef struct private_rwlock_condvar_t private_rwlock_condvar_t;
+
+/**
+ * private data of rwlock
+ */
+struct private_rwlock_t {
+
+	/**
+	 * public functions
+	 */
+	rwlock_t public;
+
+	/**
+	 * wrapped rwlock
+	 */
+	SRWLOCK srw;
+
+	/**
+	 * Thread specific shared lock count
+	 */
+	thread_value_t *shared;
+};
+
+/**
+ * private data of condvar
+ */
+struct private_rwlock_condvar_t {
+
+	/**
+	 * public interface
+	 */
+	rwlock_condvar_t public;
+
+	/**
+	 * condition variable
+	 */
+	CONDITION_VARIABLE cv;
+};
+
+METHOD(rwlock_t, read_lock, void,
+	private_rwlock_t *this)
+{
+	uintptr_t count;
+
+	/* Recursive read locks are not supported. Use a thread specific
+	 * recursiveness counter. */
+
+	count = (uintptr_t)this->shared->get(this->shared);
+	if (count == 0)
+	{
+		AcquireSRWLockShared(&this->srw);
+	}
+	this->shared->set(this->shared, (void*)(count + 1));
+}
+
+METHOD(rwlock_t, write_lock, void,
+	private_rwlock_t *this)
+{
+	AcquireSRWLockExclusive(&this->srw);
+}
+
+METHOD(rwlock_t, try_write_lock, bool,
+	private_rwlock_t *this)
+{
+	/* TODO: causes random failures and segfaults. Bug? */
+	return FALSE;
+	return TryAcquireSRWLockExclusive(&this->srw);
+}
+
+METHOD(rwlock_t, unlock, void,
+	private_rwlock_t *this)
+{
+	uintptr_t count;
+
+	count = (uintptr_t)this->shared->get(this->shared);
+	switch (count)
+	{
+		case 0:
+			ReleaseSRWLockExclusive(&this->srw);
+			break;
+		case 1:
+			ReleaseSRWLockShared(&this->srw);
+			/* fall */
+		default:
+			this->shared->set(this->shared, (void*)(count - 1));
+			break;
+	}
+}
+
+METHOD(rwlock_t, destroy, void,
+	private_rwlock_t *this)
+{
+	this->shared->destroy(this->shared);
+	free(this);
+}
+
+/*
+ * see header file
+ */
+rwlock_t *rwlock_create(rwlock_type_t type)
+{
+	private_rwlock_t *this;
+
+	INIT(this,
+		.public = {
+			.read_lock = _read_lock,
+			.write_lock = _write_lock,
+			.try_write_lock = _try_write_lock,
+			.unlock = _unlock,
+			.destroy = _destroy,
+		},
+		.shared = thread_value_create(NULL),
+	);
+
+	InitializeSRWLock(&this->srw);
+
+	return &this->public;
+}
+
+METHOD(rwlock_condvar_t, timed_wait, bool,
+	private_rwlock_condvar_t *this, rwlock_t *pubrwlock, u_int timeout)
+{
+	private_rwlock_t *rwlock = (private_rwlock_t*)pubrwlock;
+	bool ret;
+
+	thread_set_active_condvar(&this->cv);
+
+	ret = SleepConditionVariableSRW(&this->cv, &rwlock->srw, timeout, 0);
+
+	thread_set_active_condvar(NULL);
+
+	return ret == 0;
+}
+
+METHOD(rwlock_condvar_t, wait_, void,
+	private_rwlock_condvar_t *this, rwlock_t *lock)
+{
+	timed_wait(this, lock, INFINITE);
+}
+
+METHOD(rwlock_condvar_t, timed_wait_abs, bool,
+	private_rwlock_condvar_t *this, rwlock_t *lock, timeval_t tv)
+{
+	DWORD timeout;
+	timeval_t now, diff;
+
+	time_monotonic(&now);
+	if (timercmp(&now, &tv, >))
+	{
+		return TRUE;
+	}
+	timersub(&tv, &now, &diff);
+	timeout = diff.tv_sec * 1000 + diff.tv_usec / 1000;
+
+	return timed_wait(this, lock, timeout);
+}
+
+METHOD(rwlock_condvar_t, signal_, void,
+	private_rwlock_condvar_t *this)
+{
+	WakeConditionVariable(&this->cv);
+}
+
+METHOD(rwlock_condvar_t, broadcast, void,
+	private_rwlock_condvar_t *this)
+{
+	WakeAllConditionVariable(&this->cv);
+}
+
+METHOD(rwlock_condvar_t, condvar_destroy, void,
+	private_rwlock_condvar_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+rwlock_condvar_t *rwlock_condvar_create()
+{
+	private_rwlock_condvar_t *this;
+
+	INIT(this,
+		.public = {
+			.wait = _wait_,
+			.timed_wait = _timed_wait,
+			.timed_wait_abs = _timed_wait_abs,
+			.signal = _signal_,
+			.broadcast = _broadcast,
+			.destroy = _condvar_destroy,
+		},
+	);
+
+	InitializeConditionVariable(&this->cv);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/threading/windows/semaphore.c b/src/libstrongswan/threading/windows/semaphore.c
new file mode 100644
index 0000000..29f523d
--- /dev/null
+++ b/src/libstrongswan/threading/windows/semaphore.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+#include <threading/semaphore.h>
+
+typedef struct private_semaphore_t private_semaphore_t;
+
+/**
+ * private data of a semaphore
+ */
+struct private_semaphore_t {
+	/**
+	 * public interface
+	 */
+	semaphore_t public;
+
+	/**
+	 * Handle to semaphore
+	 */
+	HANDLE handle;
+};
+
+METHOD(semaphore_t, timed_wait, bool,
+	private_semaphore_t *this, u_int timeout)
+{
+	/* use alertable wait to allow cancellation */
+	return WaitForSingleObjectEx(this->handle, timeout, TRUE) == WAIT_TIMEOUT;
+}
+
+METHOD(semaphore_t, timed_wait_abs, bool,
+	private_semaphore_t *this, timeval_t tv)
+{
+	DWORD timeout;
+	timeval_t now, diff;
+
+	time_monotonic(&now);
+	if (timercmp(&now, &tv, >))
+	{
+		return TRUE;
+	}
+	timersub(&tv, &now, &diff);
+	timeout = diff.tv_sec * 1000 + diff.tv_usec / 1000;
+
+	return timed_wait(this, timeout);
+}
+
+METHOD(semaphore_t, wait_, void,
+	private_semaphore_t *this)
+{
+	timed_wait(this, INFINITE);
+}
+
+METHOD(semaphore_t, post, void,
+	private_semaphore_t *this)
+{
+	ReleaseSemaphore(this->handle, 1, NULL);
+}
+
+METHOD(semaphore_t, destroy, void,
+	private_semaphore_t *this)
+{
+	CloseHandle(this->handle);
+	free(this);
+}
+
+/*
+ * Described in header
+ */
+semaphore_t *semaphore_create(u_int value)
+{
+	private_semaphore_t *this;
+
+	INIT(this,
+		.public = {
+			.wait = _wait_,
+			.timed_wait = _timed_wait,
+			.timed_wait_abs = _timed_wait_abs,
+			.post = _post,
+			.destroy = _destroy,
+		},
+		/* our API does not have an upper limit, but Windows requires one.
+		 * 0xFFFFFFF (268435455) is the highest value for which Windows does
+		 * not return ERROR_INVALID_PARAMETER, and should be sufficient. */
+		.handle = CreateSemaphore(NULL, value, 0xFFFFFFF, NULL),
+	);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/threading/windows/spinlock.c b/src/libstrongswan/threading/windows/spinlock.c
new file mode 100644
index 0000000..155dd56
--- /dev/null
+++ b/src/libstrongswan/threading/windows/spinlock.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 <library.h>
+#include <threading/spinlock.h>
+
+typedef struct private_spinlock_t private_spinlock_t;
+
+/**
+ * private data of spinlock
+ */
+struct private_spinlock_t {
+
+	/**
+	 * public functions
+	 */
+	spinlock_t public;
+
+	/**
+	 * wrapped critical section
+	 */
+	CRITICAL_SECTION cs;
+};
+
+METHOD(spinlock_t, lock, void,
+	private_spinlock_t *this)
+{
+	EnterCriticalSection(&this->cs);
+}
+
+METHOD(spinlock_t, unlock, void,
+	private_spinlock_t *this)
+{
+	LeaveCriticalSection(&this->cs);
+}
+
+METHOD(spinlock_t, destroy, void,
+	private_spinlock_t *this)
+{
+	DeleteCriticalSection(&this->cs);
+	free(this);
+}
+
+/*
+ * see header file
+ */
+spinlock_t *spinlock_create()
+{
+	private_spinlock_t *this;
+
+	INIT(this,
+		.public = {
+			.lock = _lock,
+			.unlock = _unlock,
+			.destroy = _destroy,
+		},
+	);
+
+	/* Usually the wait time in a spinlock should be short, so we could have
+	 * a high spincount. But having a large/INFINITE spincount does not scale
+	 * that well where a spinlock is not the perfect choice for a lock. We
+	 * choose the spincount quite arbitrary, so we go to wait if it is not
+	 * much more expensive than spinning. */
+	InitializeCriticalSectionAndSpinCount(&this->cs, 256);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/threading/windows/thread.c b/src/libstrongswan/threading/windows/thread.c
new file mode 100644
index 0000000..e76758f
--- /dev/null
+++ b/src/libstrongswan/threading/windows/thread.c
@@ -0,0 +1,677 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 "thread.h"
+
+#include <utils/debug.h>
+#include <threading/spinlock.h>
+#include <threading/thread.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+
+
+typedef struct private_thread_t private_thread_t;
+
+struct private_thread_t {
+
+	/**
+	 * Public interface.
+	 */
+	thread_t public;
+
+	/**
+	 * GetCurrentThreadId() of thread
+	 */
+	DWORD id;
+
+	/**
+	 * Printable thread id returned by thread_current_id()
+	 */
+	u_int tid;
+
+	/**
+	 * Windows thread handle
+	 */
+	HANDLE handle;
+
+	/**
+	 * Main function of this thread (NULL for the main thread).
+	 */
+	thread_main_t main;
+
+	/**
+	 * Argument for the main function.
+	 */
+	void *arg;
+
+	/**
+	 * Thread return value
+	 */
+	void *ret;
+
+	/**
+	 * Stack of cleanup handlers, as cleanup_t
+	 */
+	array_t *cleanup;
+
+	/**
+	 * Thread specific values for this thread
+	 */
+	hashtable_t *tls;
+
+	/**
+	 * Thread terminated?
+	 */
+	bool terminated;
+
+	/**
+	 * Thread detached?
+	 */
+	bool detached;
+
+	/**
+	 * Is thread in cancellable state
+	 */
+	bool cancelability;
+
+	/**
+	 * Has the thread been cancelled by thread->cancel()?
+	 */
+	bool canceled;
+
+	/**
+	 * Did we schedule an APC to docancel()?
+	 */
+	bool cancel_pending;
+
+	/**
+	 * Active condition variable thread is waiting in, if any
+	 */
+	CONDITION_VARIABLE *condvar;
+};
+
+/**
+ * Global list of threads, GetCurrentThreadId() => private_thread_t
+ */
+static hashtable_t *threads;
+
+/**
+ * Lock for threads table
+ */
+static spinlock_t *threads_lock;
+
+/**
+ * Counter to assign printable thread IDs
+ */
+static u_int threads_ids = 0;
+
+/**
+ * Forward declaration
+ */
+static private_thread_t *create_internal(DWORD id);
+
+/**
+ * Set leak detective state
+ */
+static inline bool set_leak_detective(bool state)
+{
+#ifdef LEAK_DETECTIVE
+	if (lib && lib->leak_detective)
+	{
+		return lib->leak_detective->set_state(lib->leak_detective, state);
+	}
+#endif
+	return FALSE;
+}
+
+/**
+ * Store thread in index
+ */
+static void put_thread(private_thread_t *this)
+{
+	bool old;
+
+	old = set_leak_detective(FALSE);
+	threads_lock->lock(threads_lock);
+
+	threads->put(threads, (void*)(uintptr_t)this->id, this);
+
+	threads_lock->unlock(threads_lock);
+	set_leak_detective(old);
+}
+
+/**
+ * Remove thread from index
+ */
+static void remove_thread(private_thread_t *this)
+{
+	bool old;
+
+	old = set_leak_detective(FALSE);
+	threads_lock->lock(threads_lock);
+
+	threads->remove(threads, (void*)(uintptr_t)this->id);
+
+	threads_lock->unlock(threads_lock);
+	set_leak_detective(old);
+}
+
+/**
+ * Get thread data for calling thread
+ */
+static private_thread_t *get_current_thread()
+{
+	private_thread_t *this;
+
+	threads_lock->lock(threads_lock);
+
+	this = threads->get(threads, (void*)(uintptr_t)GetCurrentThreadId());
+
+	threads_lock->unlock(threads_lock);
+
+	if (!this)
+	{
+		this = create_internal(GetCurrentThreadId());
+		put_thread(this);
+	}
+
+	return this;
+}
+
+/**
+ * See header.
+ */
+void* thread_tls_put(void *key, void *value)
+{
+	private_thread_t *thread;
+	bool old;
+
+	thread = get_current_thread();
+
+	old = set_leak_detective(FALSE);
+	value = thread->tls->put(thread->tls, key, value);
+	set_leak_detective(old);
+
+	return value;
+}
+
+/**
+ * See header.
+ */
+void* thread_tls_get(void *key)
+{
+	private_thread_t *thread;
+	void *value;
+	bool old;
+
+	thread = get_current_thread();
+
+	old = set_leak_detective(FALSE);
+	value = thread->tls->get(thread->tls, key);
+	set_leak_detective(old);
+
+	return value;
+}
+
+/**
+ * See header.
+ */
+void* thread_tls_remove(void *key)
+{
+	private_thread_t *thread;
+	void *value;
+	bool old;
+
+	thread = get_current_thread();
+
+	old = set_leak_detective(FALSE);
+	threads_lock->lock(threads_lock);
+	value = thread->tls->remove(thread->tls, key);
+	threads_lock->unlock(threads_lock);
+	set_leak_detective(old);
+
+	return value;
+}
+
+/**
+ * Thread cleanup data
+ */
+typedef struct {
+	/** Cleanup callback function */
+	thread_cleanup_t cb;
+	/** Argument provided to the cleanup function */
+	void *arg;
+} cleanup_t;
+
+/**
+ * Invoke pushed/tls cleanup handlers
+ */
+static void docleanup(private_thread_t *this)
+{
+	enumerator_t *enumerator;
+	cleanup_t cleanup, *tls;
+	bool old;
+
+	old = set_leak_detective(FALSE);
+
+	while (array_remove(this->cleanup, -1, &cleanup))
+	{
+		set_leak_detective(old);
+		cleanup.cb(cleanup.arg);
+		set_leak_detective(FALSE);
+	}
+
+	threads_lock->lock(threads_lock);
+	enumerator = this->tls->create_enumerator(this->tls);
+	while (enumerator->enumerate(enumerator, NULL, &tls))
+	{
+		this->tls->remove_at(this->tls, enumerator);
+
+		set_leak_detective(old);
+		thread_tls_cleanup(tls);
+		set_leak_detective(FALSE);
+	}
+	enumerator->destroy(enumerator);
+	threads_lock->unlock(threads_lock);
+
+	set_leak_detective(old);
+}
+
+/**
+ * Clean up and destroy a thread
+ */
+static void destroy(private_thread_t *this)
+{
+	bool old;
+
+	docleanup(this);
+
+	old = set_leak_detective(FALSE);
+
+	array_destroy(this->cleanup);
+	this->tls->destroy(this->tls);
+	if (this->handle)
+	{
+		CloseHandle(this->handle);
+	}
+	free(this);
+
+	set_leak_detective(old);
+}
+
+/**
+ * End a thread, destroy when detached
+ */
+static void end_thread(private_thread_t *this)
+{
+	if (this->detached)
+	{
+		remove_thread(this);
+		destroy(this);
+	}
+	else
+	{
+		this->terminated = TRUE;
+		docleanup(this);
+	}
+}
+
+/**
+ * See header.
+ */
+void thread_set_active_condvar(CONDITION_VARIABLE *condvar)
+{
+	private_thread_t *thread;
+
+	thread = get_current_thread();
+
+	threads_lock->lock(threads_lock);
+	thread->condvar = condvar;
+	threads_lock->unlock(threads_lock);
+
+	/* this is a cancellation point, as condvar wait is one */
+	SleepEx(0, TRUE);
+}
+
+/**
+ * APC to cancel a thread
+ */
+static void WINAPI docancel(ULONG_PTR dwParam)
+{
+	private_thread_t *this = (private_thread_t*)dwParam;
+
+	/* make sure cancel() does not access this anymore */
+	threads_lock->lock(threads_lock);
+	threads_lock->unlock(threads_lock);
+
+	end_thread(this);
+	ExitThread(0);
+}
+
+METHOD(thread_t, cancel, void,
+	private_thread_t *this)
+{
+	this->canceled = TRUE;
+	if (this->cancelability)
+	{
+		threads_lock->lock(threads_lock);
+		if (!this->cancel_pending)
+		{
+			this->cancel_pending = TRUE;
+			QueueUserAPC(docancel, this->handle, (uintptr_t)this);
+			if (this->condvar)
+			{
+				WakeAllConditionVariable(this->condvar);
+			}
+		}
+		threads_lock->unlock(threads_lock);
+	}
+}
+
+METHOD(thread_t, kill_, void,
+	private_thread_t *this, int sig)
+{
+}
+
+METHOD(thread_t, detach, void,
+	private_thread_t *this)
+{
+	this->detached = TRUE;
+}
+
+METHOD(thread_t, join, void*,
+	private_thread_t *this)
+{
+	void *ret;
+
+	if (this->detached)
+	{
+		return NULL;
+	}
+
+	while (!this->terminated)
+	{
+		/* join is a cancellation point, use alertable wait */
+		WaitForSingleObjectEx(this->handle, INFINITE, TRUE);
+	}
+
+	ret = this->ret;
+
+	remove_thread(this);
+	destroy(this);
+
+	return ret;
+}
+
+/**
+ * Main function wrapper for threads
+ */
+static DWORD thread_cb(private_thread_t *this)
+{
+	/* Enable cancelability once the thread starts. We must check for any
+	 * pending cancellation request an queue the APC that gets executed
+	 * at the first cancellation point. */
+	this->cancelability = TRUE;
+	if (this->canceled)
+	{
+		cancel(this);
+	}
+
+	this->ret = this->main(this->arg);
+
+	end_thread(this);
+
+	return 0;
+}
+
+/**
+ * Create an internal thread object.
+ */
+static private_thread_t *create_internal(DWORD id)
+{
+	private_thread_t *this;
+	bool old;
+
+	old = set_leak_detective(FALSE);
+
+	INIT(this,
+		.public = {
+			.cancel = _cancel,
+			.kill = _kill_,
+			.detach = _detach,
+			.join = _join,
+		},
+		.cleanup = array_create(sizeof(cleanup_t), 0),
+		.tls = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4),
+		.id = id,
+		.cancelability = TRUE,
+	);
+
+	set_leak_detective(old);
+
+	threads_lock->lock(threads_lock);
+	this->tid = threads_ids++;
+	threads_lock->unlock(threads_lock);
+
+	if (id)
+	{
+		this->handle = OpenThread(THREAD_ALL_ACCESS, FALSE, id);
+	}
+	return this;
+}
+
+/**
+ * Described in header.
+ */
+thread_t *thread_create(thread_main_t main, void *arg)
+{
+	private_thread_t *this;
+
+	this = create_internal(0);
+
+	this->main = main;
+	this->arg = arg;
+	/* not cancellable until started */
+	this->cancelability = FALSE;
+
+	this->handle = CreateThread(NULL, 0, (void*)thread_cb, this,
+								CREATE_SUSPENDED, &this->id);
+	if (!this->handle)
+	{
+		destroy(this);
+		return NULL;
+	}
+
+	put_thread(this);
+
+	DBG2(DBG_LIB, "created thread %u", this->id);
+
+	ResumeThread(this->handle);
+
+	return &this->public;
+}
+
+/**
+ * Described in header.
+ */
+thread_t *thread_current()
+{
+	return &get_current_thread()->public;
+}
+
+/**
+ * Described in header.
+ */
+u_int thread_current_id()
+{
+	return get_current_thread()->tid;
+}
+
+/**
+ * Described in header.
+ */
+void thread_cleanup_push(thread_cleanup_t cb, void *arg)
+{
+	private_thread_t *this;
+	cleanup_t cleanup = {
+		.cb = cb,
+		.arg = arg,
+	};
+	bool old;
+
+	this = get_current_thread();
+
+	old = set_leak_detective(FALSE);
+	array_insert(this->cleanup, -1, &cleanup);
+	set_leak_detective(old);
+}
+
+/**
+ * Described in header
+ */
+void thread_cleanup_pop(bool execute)
+{
+	private_thread_t *this;
+	cleanup_t cleanup = {};
+	bool old;
+
+	this = get_current_thread();
+
+	old = set_leak_detective(FALSE);
+	array_remove(this->cleanup, -1, &cleanup);
+	set_leak_detective(old);
+
+	if (execute)
+	{
+		cleanup.cb(cleanup.arg);
+	}
+}
+
+/**
+ * Described in header.
+ */
+bool thread_cancelability(bool enable)
+{
+	private_thread_t *this;
+	bool old;
+
+	this = get_current_thread();
+	old = this->cancelability;
+	this->cancelability = enable;
+
+	if (enable && !old && this->canceled)
+	{
+		cancel(this);
+	}
+	return old;
+}
+
+/**
+ * Described in header.
+ */
+void thread_cancellation_point()
+{
+	bool old;
+
+	old = thread_cancelability(TRUE);
+	SleepEx(0, TRUE);
+	thread_cancelability(old);
+}
+
+/**
+ * Described in header.
+ */
+void thread_exit(void *val)
+{
+	private_thread_t *this;
+
+	this = get_current_thread();
+	this->ret = val;
+
+	end_thread(this);
+	ExitThread(0);
+}
+
+/**
+ * Clean up thread data while it detaches
+ */
+static void cleanup_tls()
+{
+	private_thread_t *this;
+	bool old;
+
+	old = set_leak_detective(FALSE);
+	threads_lock->lock(threads_lock);
+
+	this = threads->remove(threads, (void*)(uintptr_t)GetCurrentThreadId());
+
+	threads_lock->unlock(threads_lock);
+	set_leak_detective(old);
+
+	if (this)
+	{
+		/* If the thread exited, but has not been joined, it is in terminated
+		 * state. We must not mangle it, as we target externally spawned
+		 * threads only. */
+		if (!this->terminated && !this->detached)
+		{
+			destroy(this);
+		}
+	}
+}
+
+/**
+ * DllMain called for dll events
+ */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+	switch (fdwReason)
+	{
+		case DLL_THREAD_DETACH:
+			cleanup_tls();
+			break;
+		default:
+			break;
+	}
+	return TRUE;
+}
+
+/*
+ * Described in header.
+ */
+void threads_init()
+{
+	threads_lock = spinlock_create();
+	threads = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4);
+
+	/* reset counter should we initialize more than once */
+	threads_ids = 0;
+
+	put_thread(create_internal(GetCurrentThreadId()));
+}
+
+/**
+ * Described in header.
+ */
+void threads_deinit()
+{
+	private_thread_t *this;
+
+	this = threads->remove(threads, (void*)(uintptr_t)GetCurrentThreadId());
+	destroy(this);
+
+	threads_lock->destroy(threads_lock);
+	threads->destroy(threads);
+}
diff --git a/src/libstrongswan/threading/windows/thread.h b/src/libstrongswan/threading/windows/thread.h
new file mode 100644
index 0000000..3f08c62
--- /dev/null
+++ b/src/libstrongswan/threading/windows/thread.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef WINDOWS_THREAD_H_
+#define WINDOWS_THREAD_H_
+
+/* for conditionVariables, Vista */
+#define _WIN32_WINNT 0x0600
+#include <library.h>
+
+/**
+ * @defgroup windowsthread windows
+ * @ingroup threading
+ *
+ * @defgroup threadwindows thread
+ * @{ @ingroup windowsthread
+ */
+
+/**
+ * Set active condvar of a thread before waiting in it.
+ *
+ * @param condvar	active condition variable, NULL to unset
+ */
+void thread_set_active_condvar(CONDITION_VARIABLE *condvar);
+
+/**
+ * Set a thread specific value on the current thread.
+ *
+ * @param key		unique key specifying the TLS variable
+ * @param value		value to set
+ * @return			old value for key, if any
+ */
+void* thread_tls_put(void *key, void *value);
+
+/**
+ * Get a thread specific value from the current thread.
+ *
+ * @param key		unique key specifying the TLS variable
+ * @return			value for key, if any
+ */
+void* thread_tls_get(void *key);
+
+/**
+ * Remove a thread specific value from the current thread.
+ *
+ * @param key		unique key specifying the TLS variable
+ * @return			value for key, if any
+ */
+void* thread_tls_remove(void *key);
+
+/**
+ * Cleanup function for thread specific value.
+ *
+ * This is called whenever a thread exits to clean up thread specific data.
+ *
+ * This function is actually implemented in thread_value.c.
+ *
+ * @param value		value, as passed to thread_tls_put()
+ */
+void thread_tls_cleanup(void *value);
+
+#endif /** WINDOWS_THREAD_H_ @}*/
diff --git a/src/libstrongswan/threading/windows/thread_value.c b/src/libstrongswan/threading/windows/thread_value.c
new file mode 100644
index 0000000..d7bd7e6
--- /dev/null
+++ b/src/libstrongswan/threading/windows/thread_value.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 "thread.h"
+
+#include <threading/thread_value.h>
+
+
+typedef struct private_thread_value_t private_thread_value_t;
+
+/**
+ * Unified thread_value_t implementation
+ */
+struct private_thread_value_t {
+
+	/**
+	 * Public interface.
+	 */
+	thread_value_t public;
+
+	union {
+
+		/**
+		 * Cleanup function
+		 */
+		thread_cleanup_t cleanup;
+
+		/**
+		 * Windows TLS index, if used
+		 */
+		DWORD index;
+	};
+};
+
+/**
+ * TLS entry
+ */
+typedef struct {
+	/** TLS value */
+	void *value;
+	/** cleanup handler function */
+	thread_cleanup_t cleanup;
+} entry_t;
+
+/**
+ * See windows/thread.h
+ */
+void thread_tls_cleanup(void *value)
+{
+	entry_t *entry = (entry_t*)value;
+
+	if (entry->cleanup)
+	{
+		entry->cleanup(entry->value);
+	}
+	free(entry);
+}
+
+METHOD(thread_value_t, tls_set, void,
+	private_thread_value_t *this, void *val)
+{
+	entry_t *entry;
+
+	if (val)
+	{
+		INIT(entry,
+			.cleanup = this->cleanup,
+			.value = val,
+		);
+
+		free(thread_tls_put(this, entry));
+	}
+	else
+	{
+		free(thread_tls_remove(this));
+	}
+}
+
+METHOD(thread_value_t, tls_get, void*,
+	private_thread_value_t *this)
+{
+	entry_t *entry;
+
+	entry = thread_tls_get(this);
+	if (entry)
+	{
+		return entry->value;
+	}
+	return NULL;
+}
+
+METHOD(thread_value_t, tls_destroy, void,
+	private_thread_value_t *this)
+{
+	entry_t *entry;
+
+	entry = thread_tls_remove(this);
+	if (entry)
+	{
+		thread_tls_cleanup(entry);
+	}
+	free(this);
+}
+
+METHOD(thread_value_t, tls_set_index, void,
+	private_thread_value_t *this, void *val)
+{
+	TlsSetValue(this->index, val);
+}
+
+METHOD(thread_value_t, tls_get_index, void*,
+	private_thread_value_t *this)
+{
+	return TlsGetValue(this->index);
+}
+
+METHOD(thread_value_t, tls_destroy_index, void,
+	private_thread_value_t *this)
+{
+	TlsFree(this->index);
+	free(this);
+}
+
+/**
+ * Described in header.
+ */
+thread_value_t *thread_value_create(thread_cleanup_t cleanup)
+{
+	private_thread_value_t *this;
+	DWORD index = TLS_OUT_OF_INDEXES;
+
+	/* we have two implementations: Windows Tls* functions do not support
+	 * callbacks and has limited instances. We use it nonetheless if possible,
+	 * especially as leak detective relies on TLS, but we have to mangle
+	 * leak detective state for TLS storage. */
+
+	if (!cleanup)
+	{
+		index = TlsAlloc();
+	}
+
+	if (index == TLS_OUT_OF_INDEXES)
+	{
+		INIT(this,
+			.public = {
+				.set = _tls_set,
+				.get = _tls_get,
+				.destroy = _tls_destroy,
+			},
+			.cleanup = cleanup,
+		);
+	}
+	else
+	{
+		INIT(this,
+			.public = {
+				.set = _tls_set_index,
+				.get = _tls_get_index,
+				.destroy = _tls_destroy_index,
+			},
+			.index = index,
+		);
+	}
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
index f158462..e694cae 100644
--- a/src/libstrongswan/utils/backtrace.c
+++ b/src/libstrongswan/utils/backtrace.c
@@ -1,6 +1,7 @@
 /*
- * Copyright (C) 2006-2008 Martin Willi
+ * Copyright (C) 2006-2013 Martin Willi
  * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2013 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
@@ -15,20 +16,37 @@
 
 #define _GNU_SOURCE
 
-#ifdef HAVE_DLADDR
-# include <dlfcn.h>
-#endif /* HAVE_DLADDR */
-
 #ifdef HAVE_BACKTRACE
 # include <execinfo.h>
 #endif /* HAVE_BACKTRACE */
-
+#ifdef HAVE_DBGHELP
+# include <winsock2.h>
+# include <windows.h>
+# include <dbghelp.h>
+#endif /* HAVE_DBGHELP */
 #include <string.h>
 
 #include "backtrace.h"
 
 #include <utils/debug.h>
 
+#ifdef WIN32
+# include <psapi.h>
+/* missing in MinGW */
+#ifdef WIN64
+#ifndef GetModuleInformation
+WINBOOL K32GetModuleInformation(HANDLE hProcess, HMODULE hModule,
+								LPMODULEINFO lpmodinfo, DWORD cb);
+#define GetModuleInformation K32GetModuleInformation
+#endif /* !GetModuleInformation */
+#ifndef GetModuleFileNameEx
+DWORD K32GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule,
+							  LPTSTR lpFilename, DWORD nSize);
+#define GetModuleFileNameEx K32GetModuleFileNameExA
+#endif /* !GetModuleFileNameEx */
+#endif /* WIN64 */
+#endif
+
 typedef struct private_backtrace_t private_backtrace_t;
 
 /**
@@ -79,12 +97,10 @@ static void println(FILE *file, char *format, ...)
 	va_end(args);
 }
 
-#ifdef HAVE_DLADDR
-
 /**
  * Same as tty_escape_get(), but for a potentially NULL FILE*
  */
-static char* esc(FILE *file, tty_escape_t escape)
+static inline char* esc(FILE *file, tty_escape_t escape)
 {
 	if (file)
 	{
@@ -93,6 +109,35 @@ static char* esc(FILE *file, tty_escape_t escape)
 	return "";
 }
 
+#ifdef HAVE_DBGHELP
+
+#include <dbghelp.h>
+#include <threading/mutex.h>
+
+/**
+ * Mutex to access non-thread-safe dbghelp functions
+ */
+static mutex_t *dbghelp_mutex;
+
+void backtrace_init()
+{
+	SymSetOptions(SYMOPT_LOAD_LINES);
+	SymInitialize(GetCurrentProcess(), NULL, TRUE);
+	dbghelp_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+}
+
+void backtrace_deinit()
+{
+	dbghelp_mutex->destroy(dbghelp_mutex);
+	SymCleanup(GetCurrentProcess());
+}
+
+#elif defined(HAVE_DLADDR) || defined(HAVE_BFD_H)
+
+#ifdef HAVE_DLADDR
+#include <dlfcn.h>
+#endif
+
 #ifdef HAVE_BFD_H
 
 #include <bfd.h>
@@ -352,7 +397,6 @@ static void print_sourceline(FILE *file, char *filename, void *ptr, void* base)
 	snprintf(buf, sizeof(buf), "addr2line -e %s %p", filename, ptr);
 #endif /* __APPLE__ */
 
-
 	output = popen(buf, "r");
 	if (output)
 	{
@@ -375,7 +419,7 @@ static void print_sourceline(FILE *file, char *filename, void *ptr, void* base)
 
 #endif /* HAVE_BFD_H */
 
-#else /* !HAVE_DLADDR */
+#else /* !HAVE_DLADDR && !HAVE_DBGHELP */
 
 void backtrace_init() {}
 void backtrace_deinit() {}
@@ -385,7 +429,7 @@ void backtrace_deinit() {}
 METHOD(backtrace_t, log_, void,
 	private_backtrace_t *this, FILE *file, bool detailed)
 {
-#if defined(HAVE_BACKTRACE) || defined(HAVE_LIBUNWIND_H)
+#if defined(HAVE_BACKTRACE) || defined(HAVE_LIBUNWIND_H) || defined(WIN32)
 	size_t i;
 	char **strings = NULL;
 
@@ -425,7 +469,83 @@ METHOD(backtrace_t, log_, void,
 			}
 		}
 		else
-#endif /* HAVE_DLADDR */
+#elif defined(HAVE_DBGHELP)
+		struct {
+			SYMBOL_INFO hdr;
+			char buf[128];
+		} symbol;
+		char filename[MAX_PATH];
+		HINSTANCE module;
+		HANDLE process;
+		DWORD64 displace, frame;
+
+		process = GetCurrentProcess();
+		frame = (uintptr_t)this->frames[i];
+
+		memset(&symbol, 0, sizeof(symbol));
+		symbol.hdr.SizeOfStruct = sizeof(symbol.hdr);
+		symbol.hdr.MaxNameLen = sizeof(symbol.buf) - 1;
+
+		dbghelp_mutex->lock(dbghelp_mutex);
+
+		module = (HINSTANCE)SymGetModuleBase64(process, frame);
+
+		if (module && GetModuleFileName(module, filename, sizeof(filename)))
+		{
+			if (SymFromAddr(process, frame, &displace, &symbol.hdr))
+			{
+				println(file, "  %s%s%s @ %p (%s%s%s+0x%tx) [%p]",
+						esc(file, TTY_FG_YELLOW), filename,
+						esc(file, TTY_FG_DEF), (void*)module,
+						esc(file, TTY_FG_RED), symbol.hdr.Name,
+						esc(file, TTY_FG_DEF), displace,
+						this->frames[i]);
+			}
+			else
+			{
+				println(file, "  %s%s%s @ %p [%p]",
+						esc(file, TTY_FG_YELLOW), filename,
+						esc(file, TTY_FG_DEF), (void*)module, this->frames[i]);
+			}
+			if (detailed)
+			{
+				IMAGEHLP_LINE64 line;
+				DWORD off;
+
+				memset(&line, 0, sizeof(line));
+				line.SizeOfStruct = sizeof(line);
+
+				if (SymGetLineFromAddr64(process, frame, &off, &line))
+				{
+
+					println(file, "    -> %s%s:%u%s", esc(file, TTY_FG_GREEN),
+							line.FileName, line.LineNumber,
+							esc(file, TTY_FG_DEF));
+				}
+			}
+		}
+		else
+#elif defined(WIN32)
+		HMODULE module;
+		MODULEINFO info;
+		char filename[MAX_PATH];
+
+		if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+						this->frames[i], &module) &&
+			GetModuleInformation(GetCurrentProcess(), module,
+						&info, sizeof(info)) &&
+			GetModuleFileNameEx(GetCurrentProcess(), module,
+						filename, sizeof(filename)))
+		{
+			println(file, "  %s%s%s @ %p [%p]",
+					esc(file, TTY_FG_YELLOW), filename,
+					esc(file, TTY_FG_DEF), info.lpBaseOfDll, this->frames[i]);
+#ifdef HAVE_BFD_H
+			print_sourceline(file, filename, this->frames[i], info.lpBaseOfDll);
+#endif /* HAVE_BFD_H */
+		}
+		else
+#endif /* HAVE_DLADDR/HAVE_DBGHELP */
 		{
 #ifdef HAVE_BACKTRACE
 			if (!strings)
@@ -442,10 +562,13 @@ METHOD(backtrace_t, log_, void,
 				println(file, "    %p", this->frames[i]);
 			}
 		}
+#ifdef HAVE_DBGHELP
+		dbghelp_mutex->unlock(dbghelp_mutex);
+#endif
 	}
 	free(strings);
 #else /* !HAVE_BACKTRACE && !HAVE_LIBUNWIND_H */
-	println(file, "no support for backtrace()/libunwind");
+	println(file, "no support for capturing backtraces");
 #endif /* HAVE_BACKTRACE/HAVE_LIBUNWIND_H */
 }
 
@@ -470,7 +593,40 @@ METHOD(backtrace_t, contains_function, bool,
 			}
 		}
 	}
-#endif /* HAVE_DLADDR */
+#elif defined(HAVE_DBGHELP)
+	int i, j;
+	HANDLE process;
+
+	process = GetCurrentProcess();
+
+	dbghelp_mutex->lock(dbghelp_mutex);
+
+	for (i = 0; i < this->frame_count; i++)
+	{
+		struct {
+			SYMBOL_INFO hdr;
+			char buf[128];
+		} symbol;
+
+		memset(&symbol, 0, sizeof(symbol));
+		symbol.hdr.SizeOfStruct = sizeof(symbol.hdr);
+		symbol.hdr.MaxNameLen = sizeof(symbol.buf) - 1;
+
+		if (SymFromAddr(process, (DWORD64)this->frames[i], NULL, &symbol.hdr))
+		{
+			for (j = 0; j < count; j++)
+			{
+				if (streq(symbol.hdr.Name, function[j]))
+				{
+					dbghelp_mutex->unlock(dbghelp_mutex);
+					return TRUE;
+				}
+			}
+		}
+	}
+
+	dbghelp_mutex->unlock(dbghelp_mutex);
+#endif /* HAVE_DLADDR/HAVE_DBGHELP */
 	return FALSE;
 }
 
@@ -584,6 +740,66 @@ static inline int backtrace_unwind(void **frames, int count)
 }
 #endif /* HAVE_UNWIND */
 
+#ifdef HAVE_DBGHELP
+
+/**
+ * Windows dbghelp variant for glibc backtrace()
+ */
+static inline int backtrace_win(void **frames, int count)
+{
+	STACKFRAME frame;
+	HANDLE process, thread;
+	DWORD machine;
+	CONTEXT context;
+	int got = 0;
+
+	memset(&frame, 0, sizeof(frame));
+	memset(&context, 0, sizeof(context));
+
+	process = GetCurrentProcess();
+	thread = GetCurrentThread();
+
+#ifdef __x86_64
+	machine = IMAGE_FILE_MACHINE_AMD64;
+
+	frame.AddrPC.Offset = context.Rip;
+	frame.AddrPC.Mode = AddrModeFlat;
+	frame.AddrStack.Offset = context.Rsp;
+	frame.AddrStack.Mode = AddrModeFlat;
+	frame.AddrFrame.Offset = context.Rbp;
+	frame.AddrFrame.Mode = AddrModeFlat;
+#else /* x86 */
+	machine = IMAGE_FILE_MACHINE_I386;
+
+	frame.AddrPC.Offset = context.Eip;
+	frame.AddrPC.Mode = AddrModeFlat;
+	frame.AddrStack.Offset = context.Esp;
+	frame.AddrStack.Mode = AddrModeFlat;
+	frame.AddrFrame.Offset = context.Ebp;
+	frame.AddrFrame.Mode = AddrModeFlat;
+#endif /* x86_64/x86 */
+
+	dbghelp_mutex->lock(dbghelp_mutex);
+
+	RtlCaptureContext(&context);
+
+	while (got < count)
+	{
+		if (!StackWalk64(machine, process, thread, &frame, &context,
+						 NULL, SymFunctionTableAccess, SymGetModuleBase, NULL))
+		{
+			break;
+		}
+		frames[got++] = (void*)frame.AddrPC.Offset;
+	}
+
+	dbghelp_mutex->unlock(dbghelp_mutex);
+
+	return got;
+}
+
+#endif /* HAVE_DBGHELP */
+
 /**
  * Get implementation methods of backtrace_t
  */
@@ -612,7 +828,12 @@ backtrace_t *backtrace_create(int skip)
 	frame_count = backtrace_unwind(frames, countof(frames));
 #elif defined(HAVE_BACKTRACE)
 	frame_count = backtrace(frames, countof(frames));
-#endif /* HAVE_BACKTRACE */
+#elif defined(HAVE_DBGHELP)
+	frame_count = backtrace_win(frames, countof(frames));
+#elif defined(WIN32)
+	frame_count = CaptureStackBackTrace(skip, countof(frames), frames, NULL);
+	skip = 0;
+#endif
 	frame_count = max(frame_count - skip, 0);
 	this = malloc(sizeof(private_backtrace_t) + frame_count * sizeof(void*));
 	memcpy(this->frames, frames + skip, frame_count * sizeof(void*));
diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c
index c5e90b6..923b7d4 100644
--- a/src/libstrongswan/utils/capabilities.c
+++ b/src/libstrongswan/utils/capabilities.c
@@ -17,24 +17,27 @@
 
 #include "capabilities.h"
 
+#include <utils/debug.h>
+
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
+#include <unistd.h>
+
+#ifndef WIN32
 #include <pwd.h>
 #include <grp.h>
-#include <unistd.h>
 #ifdef HAVE_PRCTL
 # include <sys/prctl.h>
 #endif /* HAVE_PRCTL */
 
-#include <utils/debug.h>
-
 #if !defined(HAVE_GETPWNAM_R) || \
     !defined(HAVE_GETGRNAM_R) || \
     !defined(HAVE_GETPWUID_R)
 # include <threading/mutex.h>
 # define EMULATE_R_FUNCS
 #endif
+#endif /* !WIN32 */
 
 typedef struct private_capabilities_t private_capabilities_t;
 
@@ -76,6 +79,8 @@ struct private_capabilities_t {
 #endif
 };
 
+#ifndef WIN32
+
 /**
  * Returns TRUE if the current process/user is member of the given group
  */
@@ -181,6 +186,19 @@ static bool has_capability(private_capabilities_t *this, u_int cap,
 #endif /* CAPABILITIES_NATIVE */
 }
 
+#else /* WIN32 */
+
+/**
+ * Verify that the current process has the given capability, dummy variant
+ */
+static bool has_capability(private_capabilities_t *this, u_int cap,
+						   bool *ignore)
+{
+	return TRUE;
+}
+
+#endif /* WIN32 */
+
 /**
  * Keep the given capability if it is held by the current process.  Returns
  * FALSE, if this is not the case.
@@ -232,13 +250,21 @@ METHOD(capabilities_t, check, bool,
 METHOD(capabilities_t, get_uid, uid_t,
 	private_capabilities_t *this)
 {
+#ifdef WIN32
+	return this->uid;
+#else
 	return this->uid ?: geteuid();
+#endif
 }
 
 METHOD(capabilities_t, get_gid, gid_t,
 	private_capabilities_t *this)
 {
+#ifdef WIN32
+	return this->gid;
+#else
 	return this->gid ?: getegid();
+#endif
 }
 
 METHOD(capabilities_t, set_uid, void,
@@ -256,6 +282,7 @@ METHOD(capabilities_t, set_gid, void,
 METHOD(capabilities_t, resolve_uid, bool,
 	private_capabilities_t *this, char *username)
 {
+#ifndef WIN32
 	struct passwd *pwp;
 	int err;
 
@@ -284,12 +311,14 @@ METHOD(capabilities_t, resolve_uid, bool,
 	}
 	DBG1(DBG_LIB, "resolving user '%s' failed: %s", username,
 		 err ? strerror(err) : "user not found");
+#endif /* !WIN32 */
 	return FALSE;
 }
 
 METHOD(capabilities_t, resolve_gid, bool,
 	private_capabilities_t *this, char *groupname)
 {
+#ifndef WIN32
 	struct group *grp;
 	int err;
 
@@ -318,9 +347,11 @@ METHOD(capabilities_t, resolve_gid, bool,
 	}
 	DBG1(DBG_LIB, "resolving user '%s' failed: %s", groupname,
 		 err ? strerror(err) : "group not found");
+#endif /* !WIN32 */
 	return FALSE;
 }
 
+#ifndef WIN32
 /**
  * Initialize supplementary groups for unprivileged user
  */
@@ -348,10 +379,12 @@ static bool init_supplementary_groups(private_capabilities_t *this)
 #endif /* HAVE_GETPWUID_R */
 	return res == 0;
 }
+#endif /* WIN32 */
 
 METHOD(capabilities_t, drop, bool,
 	private_capabilities_t *this)
 {
+#ifndef WIN32
 #ifdef HAVE_PRCTL
 	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
 #endif
@@ -404,6 +437,7 @@ METHOD(capabilities_t, drop, bool,
 	DBG1(DBG_LIB, "dropped capabilities, running as uid %u, gid %u",
 		 geteuid(), getegid());
 #endif /* CAPABILITIES */
+#endif /*!WIN32 */
 	return TRUE;
 }
 
diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c
index 4718171..1a9674f 100644
--- a/src/libstrongswan/utils/chunk.c
+++ b/src/libstrongswan/utils/chunk.c
@@ -24,8 +24,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
-#include <pthread.h>
 #include <ctype.h>
+#include <time.h>
 
 #include "chunk.h"
 
@@ -221,7 +221,14 @@ bool chunk_write(chunk_t chunk, char *path, mode_t mask, bool force)
 		return FALSE;
 	}
 	oldmask = umask(mask);
-	fd = fopen(path, "w");
+	fd = fopen(path,
+#ifdef WIN32
+				"wb"
+#else
+				"w"
+#endif
+	);
+
 	if (fd)
 	{
 		if (fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd) == chunk.len)
@@ -269,6 +276,12 @@ bool chunk_from_fd(int fd, chunk_t *out)
 	while (TRUE)
 	{
 		len = read(fd, buf + total, bufsize - total);
+#ifdef WIN32
+		if (len == -1 && errno == EBADF)
+		{	/* operating on a Winsock socket? */
+			len = recv(fd, buf + total, bufsize - total, 0);
+		}
+#endif
 		if (len < 0)
 		{
 			free(buf);
@@ -327,10 +340,15 @@ chunk_t *chunk_map(char *path, bool wr)
 {
 	mmaped_chunk_t *chunk;
 	struct stat sb;
-	int tmp;
+	int tmp, flags;
+
+	flags = wr ? O_RDWR : O_RDONLY;
+#ifdef WIN32
+	flags |= O_BINARY;
+#endif
 
 	INIT(chunk,
-		.fd = open(path, wr ? O_RDWR : O_RDONLY),
+		.fd = open(path, flags),
 		.wr = wr,
 	);
 
@@ -884,9 +902,9 @@ u_int64_t chunk_mac(chunk_t chunk, u_char *key)
 }
 
 /**
- * Secret key allocated randomly during first use.
+ * Secret key allocated randomly with chunk_hash_seed().
  */
-static u_char key[16];
+static u_char key[16] = {};
 
 /**
  * Static key used in case predictable hash values are required.
@@ -895,20 +913,21 @@ static u_char static_key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 							  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
 
 /**
- * Only allocate the key once
+ * See header
  */
-static pthread_once_t key_allocated = PTHREAD_ONCE_INIT;
-
-/**
- * Allocate a key on first use, we do this manually to avoid dependencies on
- * plugins.
- */
-static void allocate_key()
+void chunk_hash_seed()
 {
+	static bool seeded = FALSE;
 	ssize_t len;
 	size_t done = 0;
 	int fd;
 
+	if (seeded)
+	{
+		/* just once to have the same seed during the whole process lifetimes */
+		return;
+	}
+
 	fd = open("/dev/urandom", O_RDONLY);
 	if (fd >= 0)
 	{
@@ -932,6 +951,7 @@ static void allocate_key()
 			key[done] = (u_char)random();
 		}
 	}
+	seeded = TRUE;
 }
 
 /**
@@ -939,7 +959,6 @@ static void allocate_key()
  */
 u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
 {
-	pthread_once(&key_allocated, allocate_key);
 	/* we could use a mac of the previous hash, but this is faster */
 	return chunk_mac_inc(chunk, key, ((u_int64_t)hash) << 32 | hash);
 }
@@ -949,7 +968,6 @@ u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
  */
 u_int32_t chunk_hash(chunk_t chunk)
 {
-	pthread_once(&key_allocated, allocate_key);
 	return chunk_mac(chunk, key);
 }
 
diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h
index 33f66ca..9951ff3 100644
--- a/src/libstrongswan/utils/chunk.h
+++ b/src/libstrongswan/utils/chunk.h
@@ -30,6 +30,8 @@
 #include <alloca.h>
 #endif
 
+#include <utils/utils.h>
+
 typedef struct chunk_t chunk_t;
 
 /**
@@ -338,6 +340,15 @@ bool chunk_increment(chunk_t chunk);
 bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
 
 /**
+ * Seed initial key for chunk_hash().
+ *
+ * This call should get invoked once during startup. This is usually done
+ * by calling library_init(). Calling it multiple times is safe, it gets
+ * executed just once.
+ */
+void chunk_hash_seed();
+
+/**
  * Computes a 32 bit hash of the given chunk.
  *
  * @note The output of this function is randomized, that is, it will only
diff --git a/src/libstrongswan/utils/debug.h b/src/libstrongswan/utils/debug.h
index c46d3fe..f1c8c70 100644
--- a/src/libstrongswan/utils/debug.h
+++ b/src/libstrongswan/utils/debug.h
@@ -26,7 +26,7 @@ typedef enum level_t level_t;
 
 #include <stdio.h>
 
-#include "utils/enum.h"
+#include <utils/utils.h>
 
 /**
  * Debug message group.
diff --git a/src/libstrongswan/utils/enum.c b/src/libstrongswan/utils/enum.c
index 3db9a34..f96fe29 100644
--- a/src/libstrongswan/utils/enum.c
+++ b/src/libstrongswan/utils/enum.c
@@ -17,6 +17,7 @@
 #include <stdio.h>
 
 #include <library.h>
+#include <utils/utils.h>
 
 #include "enum.h"
 
@@ -39,7 +40,7 @@ char *enum_to_name(enum_name_t *e, int val)
 /**
  * See header.
  */
-int enum_from_name(enum_name_t *e, char *name)
+bool enum_from_name_as_int(enum_name_t *e, const char *name, int *val)
 {
 	do
 	{
@@ -49,12 +50,13 @@ int enum_from_name(enum_name_t *e, char *name)
 		{
 			if (name && strcaseeq(name, e->names[i]))
 			{
-				return e->first + i;
+				*val = e->first + i;
+				return TRUE;
 			}
 		}
 	}
 	while ((e = e->next));
-	return -1;
+	return FALSE;
 }
 
 /**
diff --git a/src/libstrongswan/utils/enum.h b/src/libstrongswan/utils/enum.h
index a2f97d0..3c03c2a 100644
--- a/src/libstrongswan/utils/enum.h
+++ b/src/libstrongswan/utils/enum.h
@@ -120,9 +120,30 @@ char *enum_to_name(enum_name_t *e, int val);
  *
  * @param e		enum names for this enum value
  * @param name	name to get enum value for
- * @return		enum value, -1 if not found
+ * @param valp	variable sized pointer receiving value
+ * @return		TRUE if enum name found, FALSE otherwise
  */
-int enum_from_name(enum_name_t *e, char *name);
+#define enum_from_name(e, name, valp) ({ \
+	int _val; \
+	int _found = enum_from_name_as_int(e, name, &_val); \
+	if (_found) \
+	{ \
+		*(valp) = _val; \
+	} \
+	_found; })
+
+/**
+ * Convert a enum string back to its enum value, integer pointer variant.
+ *
+ * This variant takes integer pointer only, use enum_from_name() to pass
+ * enum type pointers for the result.
+ *
+ * @param e		enum names for this enum value
+ * @param name	name to get enum value for
+ * @param val	integer pointer receiving value
+ * @return		TRUE if enum name found, FALSE otherwise
+ */
+bool enum_from_name_as_int(enum_name_t *e, const char *name, int *val);
 
 /**
  * printf hook function for enum_names_t.
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index e7eb63b..46ac7e8 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -15,15 +15,12 @@
  * for more details.
  */
 
-#define _GNU_SOURCE
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 #include <string.h>
 #include <stdio.h>
 
 #include "identification.h"
 
+#include <utils/utils.h>
 #include <asn1/oid.h>
 #include <asn1/asn1.h>
 #include <crypto/hashers/hasher.h>
@@ -397,14 +394,24 @@ static status_t atodn(char *src, chunk_t *dn)
 	asn1_t rdn_type;
 	state_t state = SEARCH_OID;
 	status_t status = SUCCESS;
+	char sep = '\0';
 
 	do
 	{
 		switch (state)
 		{
 			case SEARCH_OID:
-				if (*src != ' ' && *src != '/' && *src !=  ',' && *src != '\0')
+				if (!sep && *src == '/')
+				{	/* use / as separator if the string starts with a slash */
+					sep = '/';
+					break;
+				}
+				if (*src != ' ' && *src != '\0')
 				{
+					if (!sep)
+					{	/* use , as separator by default */
+						sep = ',';
+					}
 					oid.ptr = src;
 					oid.len = 1;
 					state = READ_OID;
@@ -444,7 +451,7 @@ static status_t atodn(char *src, chunk_t *dn)
 				{
 					break;
 				}
-				else if (*src != ',' && *src != '/' && *src != '\0')
+				else if (*src != sep && *src != '\0')
 				{
 					name.ptr = src;
 					name.len = 1;
@@ -457,7 +464,7 @@ static status_t atodn(char *src, chunk_t *dn)
 				state = READ_NAME;
 				/* fall-through */
 			case READ_NAME:
-				if (*src != ',' && *src != '/' && *src != '\0')
+				if (*src != sep && *src != '\0')
 				{
 					name.len++;
 					if (*src == ' ')
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index af29e21..a2bca19 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -19,14 +19,11 @@
 #include <string.h>
 #include <stdio.h>
 #include <signal.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 #include <unistd.h>
-#include <syslog.h>
-#include <netdb.h>
 #include <locale.h>
+#ifdef HAVE_DLADDR
 #include <dlfcn.h>
+#endif
 #include <time.h>
 #include <errno.h>
 
@@ -42,6 +39,7 @@
 #include "leak_detective.h"
 
 #include <library.h>
+#include <utils/utils.h>
 #include <utils/debug.h>
 #include <utils/backtrace.h>
 #include <collections/hashtable.h>
diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c
index 1170713..6f721c9 100644
--- a/src/libstrongswan/utils/optionsfrom.c
+++ b/src/libstrongswan/utils/optionsfrom.c
@@ -90,8 +90,13 @@ METHOD(options_t, from, bool,
 	}
 
 	/* determine the file size */
-	fseek(fd, 0, SEEK_END);
-	src.len = ftell(fd);
+	if (fseek(fd, 0, SEEK_END) == -1 || (src.len = ftell(fd)) == -1)
+	{
+		DBG1(DBG_LIB, "optionsfrom: unable to determine size of '%s': %s",
+			 filename, strerror(errno));
+		fclose(fd);
+		return FALSE;
+	}
 	rewind(fd);
 
 	/* allocate one byte more just in case of a missing final newline */
diff --git a/src/libstrongswan/utils/parser_helper.c b/src/libstrongswan/utils/parser_helper.c
new file mode 100644
index 0000000..4c6aa25
--- /dev/null
+++ b/src/libstrongswan/utils/parser_helper.c
@@ -0,0 +1,261 @@
+/*
+ * 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 <limits.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "parser_helper.h"
+
+#include <collections/array.h>
+
+typedef struct private_parser_helper_t private_parser_helper_t;
+typedef struct parser_helper_file_t parser_helper_file_t;
+
+struct private_parser_helper_t {
+
+	/**
+	 * Public interface.
+	 */
+	parser_helper_t public;
+
+	/**
+	 * Stack of included files, as parser_helper_file_t.
+	 */
+	array_t *files;
+
+	/**
+	 * Helper for parsing strings.
+	 */
+	bio_writer_t *writer;
+};
+
+struct parser_helper_file_t {
+
+	/**
+	 * File name
+	 */
+	char *name;
+
+	/**
+	 * File stream
+	 */
+	FILE *file;
+
+	/**
+	 * Enumerator of paths matching the most recent inclusion pattern.
+	 */
+	enumerator_t *matches;
+};
+
+/**
+ * Destroy the given file data.
+ */
+static void parser_helper_file_destroy(parser_helper_file_t *this)
+{
+	if (this->file)
+	{
+		fclose(this->file);
+	}
+	free(this->name);
+	DESTROY_IF(this->matches);
+	free(this);
+}
+
+/**
+ * Returns the current file, if any.
+ */
+static parser_helper_file_t *current_file(private_parser_helper_t *this)
+{
+	parser_helper_file_t *file;
+
+	array_get(this->files, ARRAY_TAIL, &file);
+	if (file->name)
+	{
+		return file;
+	}
+	return NULL;
+}
+
+METHOD(parser_helper_t, file_next, FILE*,
+	private_parser_helper_t *this)
+{
+	parser_helper_file_t *file, *next;
+	char *name;
+
+	array_get(this->files, ARRAY_TAIL, &file);
+	if (!file->matches && file->name)
+	{
+		array_remove(this->files, ARRAY_TAIL, NULL);
+		parser_helper_file_destroy(file);
+		/* continue with previous includes, if any */
+		array_get(this->files, ARRAY_TAIL, &file);
+	}
+	if (file->matches)
+	{
+		while (file->matches->enumerate(file->matches, &name, NULL))
+		{
+			INIT(next,
+				.name = strdup(name),
+				.file = fopen(name, "r"),
+			);
+
+			if (next->file)
+			{
+				array_insert(this->files, ARRAY_TAIL, next);
+				return next->file;
+			}
+			PARSER_DBG2(&this->public, "unable to open '%s'", name);
+			parser_helper_file_destroy(next);
+		}
+		file->matches->destroy(file->matches);
+		file->matches = NULL;
+	}
+	return NULL;
+}
+
+METHOD(parser_helper_t, file_include, void,
+	private_parser_helper_t *this, char *pattern)
+{
+	parser_helper_file_t *file;
+	char pat[PATH_MAX];
+
+	array_get(this->files, ARRAY_TAIL, &file);
+	if (!pattern || !*pattern)
+	{
+		PARSER_DBG1(&this->public, "no include pattern specified, ignored");
+		file->matches = enumerator_create_empty();
+		return;
+	}
+
+	if (!file->name || path_absolute(pattern))
+	{	/* absolute path */
+		if (snprintf(pat, sizeof(pat), "%s", pattern) >= sizeof(pat))
+		{
+			PARSER_DBG1(&this->public, "include pattern too long, ignored");
+			file->matches = enumerator_create_empty();
+			return;
+		}
+	}
+	else
+	{	/* base relative paths to the directory of the current file */
+		char *dir = path_dirname(file->name);
+		if (snprintf(pat, sizeof(pat), "%s%s%s", dir, DIRECTORY_SEPARATOR,
+					 pattern) >= sizeof(pat))
+		{
+			PARSER_DBG1(&this->public, "include pattern too long, ignored");
+			free(dir);
+			file->matches = enumerator_create_empty();
+			return;
+		}
+		free(dir);
+	}
+
+	file->matches = enumerator_create_glob(pat);
+	if (!file->matches)
+	{	/* if glob(3) is not available, try to load pattern directly */
+		file->matches = enumerator_create_single(strdup(pat), free);
+	}
+}
+
+METHOD(parser_helper_t, string_init, void,
+	private_parser_helper_t *this)
+{
+	chunk_t data;
+
+	data = this->writer->extract_buf(this->writer);
+	chunk_free(&data);
+}
+
+METHOD(parser_helper_t, string_add, void,
+	private_parser_helper_t *this, char *str)
+{
+	this->writer->write_data(this->writer, chunk_from_str(str));
+}
+
+METHOD(parser_helper_t, string_get, char*,
+	private_parser_helper_t *this)
+{
+	chunk_t data;
+
+	this->writer->write_data(this->writer, chunk_from_chars('\0'));
+	data = this->writer->extract_buf(this->writer);
+	return data.ptr;
+}
+
+METHOD(parser_helper_t, destroy, void,
+	private_parser_helper_t *this)
+{
+	array_destroy_function(this->files, (void*)parser_helper_file_destroy, NULL);
+	this->writer->destroy(this->writer);
+	free(this);
+}
+
+/**
+ * Described in header
+ */
+void parser_helper_log(int level, parser_helper_t *ctx, char *fmt, ...)
+{
+	private_parser_helper_t *this = (private_parser_helper_t*)ctx;
+	parser_helper_file_t *file;
+	char msg[8192];
+	va_list args;
+	int line;
+
+	va_start(args, fmt);
+	vsnprintf(msg, sizeof(msg), fmt, args);
+	va_end(args);
+
+	file = current_file(this);
+	line = ctx->get_lineno ? ctx->get_lineno(ctx->scanner) : 0;
+	if (file)
+	{
+		dbg(DBG_CFG, level, "%s:%d: %s", file->name, line, msg);
+	}
+	else
+	{
+		dbg(DBG_CFG, level, "%s", msg);
+	}
+}
+
+/**
+ * Described in header
+ */
+parser_helper_t *parser_helper_create(void *context)
+{
+	private_parser_helper_t *this;
+	parser_helper_file_t *sentinel;
+
+	INIT(this,
+		.public = {
+			.context = context,
+			.file_include = _file_include,
+			.file_next = _file_next,
+			.string_init = _string_init,
+			.string_add = _string_add,
+			.string_get = _string_get,
+			.destroy = _destroy,
+		},
+		.files = array_create(0, 0),
+		.writer = bio_writer_create(0),
+	);
+
+	INIT(sentinel,
+		.name = NULL,
+	);
+	array_insert(this->files, ARRAY_TAIL, sentinel);
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/utils/parser_helper.h b/src/libstrongswan/utils/parser_helper.h
new file mode 100644
index 0000000..09ed199
--- /dev/null
+++ b/src/libstrongswan/utils/parser_helper.h
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup parser_helper parser_helper
+ * @{ @ingroup utils
+ */
+
+#ifndef PARSER_HELPER_H_
+#define PARSER_HELPER_H_
+
+#include <utils/debug.h>
+#include <collections/array.h>
+#include <bio/bio_writer.h>
+
+typedef struct parser_helper_t parser_helper_t;
+
+/**
+ * Helper class for flex/bison based parsers.
+ *
+ * <code>PREFIX</code> equals whatever is configure with
+ * <code>%option prefix</code> resp. <code>%name-prefix</code>.
+ */
+struct parser_helper_t {
+
+	/**
+	 * A user defined parser context object.
+	 */
+	const void *context;
+
+	/**
+	 * Opaque object allocated by the lexer, should be set with:
+	 * @code
+	 * PREFIXlex_init_extra(helper, &helper->scanner).
+	 * @endcode
+	 */
+	void *scanner;
+
+	/**
+	 * Function to determine the current line number (defined by the lexer).
+	 *
+	 * Basically, this should be assigned to <code>PREFIXget_lineno</code>.
+	 *
+	 * @param scanner	the lexer
+	 * @return			current line number
+	 */
+	int (*get_lineno)(void *scanner);
+
+	/**
+	 * Resolves the given include pattern, relative to the location of the
+	 * current file.
+	 *
+	 * Call file_next() to open the next file.
+	 *
+	 * @param pattern	file pattern
+	 */
+	void (*file_include)(parser_helper_t *this, char *pattern);
+
+	/**
+	 * Get the next file to process.
+	 *
+	 * This will return NULL if all files matching the most recent pattern
+	 * have been handled. If there are other patterns the next call will then
+	 * return the next file matching the previous pattern.
+	 *
+	 * When hitting <code>\<\<EOF\>\></code> first call
+	 * @code
+	 * PREFIXpop_buffer_state(yyscanner);
+	 * @endcode
+	 * then call this method to check if there are more files to include for
+	 * the most recent call to file_include(), if so, call
+	 * @code
+	 * PREFIXset_in(file, helper->scanner);
+	 * PREFIXpush_buffer_state(PREFIX_create_buffer(file, YY_BUF_SIZE,
+	 * 						helper->scanner), helper->scanner);
+	 * @endcode
+	 *
+	 * If there are no more files to process check
+	 * <code>YY_CURRENT_BUFFER</code> and if it is FALSE call yyterminate().
+	 *
+	 * @return			next file to process, or NULL (see comment)
+	 */
+	FILE *(*file_next)(parser_helper_t *this);
+
+	/**
+	 * Start parsing a string, discards any currently stored data.
+	 */
+	void (*string_init)(parser_helper_t *this);
+
+	/**
+	 * Append the given string.
+	 *
+	 * @param str		string to append
+	 */
+	void (*string_add)(parser_helper_t *this, char *str);
+
+	/**
+	 * Extract the current string buffer as null-terminated string. Can only
+	 * be called once per string.
+	 *
+	 * @return			allocated string
+	 */
+	char *(*string_get)(parser_helper_t *this);
+
+	/**
+	 * Destroy this instance.
+	 */
+	void (*destroy)(parser_helper_t *this);
+};
+
+/**
+ * Log the given message either as error or warning
+ *
+ * @param level		log level
+ * @param ctx		current parser context
+ * @param fmt		error message format
+ * @param ...		additional arguments
+ */
+void parser_helper_log(int level, parser_helper_t *ctx, char *fmt, ...);
+
+#if DEBUG_LEVEL >= 1
+# define PARSER_DBG1(ctx, fmt, ...) parser_helper_log(1, ctx, fmt, ##__VA_ARGS__)
+#endif
+#if DEBUG_LEVEL >= 2
+# define PARSER_DBG2(ctx, fmt, ...) parser_helper_log(2, ctx, fmt, ##__VA_ARGS__)
+#endif
+#if DEBUG_LEVEL >= 3
+# define PARSER_DBG3(ctx, fmt, ...) parser_helper_log(3, ctx, fmt, ##__VA_ARGS__)
+#endif
+
+#ifndef PARSER_DBG1
+# define PARSER_DBG1(...) {}
+#endif
+#ifndef PARSER_DBG2
+# define PARSER_DBG2(...) {}
+#endif
+#ifndef PARSER_DBG3
+# define PARSER_DBG3(...) {}
+#endif
+
+/**
+ * Create a parser helper object
+ *
+ * @param context		user defined parser context
+ * @return				parser helper
+ */
+parser_helper_t *parser_helper_create(void *context);
+
+#endif /** PARSER_HELPER_H_ @}*/
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
index c79d4b8..466c673 100644
--- a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
@@ -1104,6 +1104,128 @@ int builtin_vprintf(const char *format, va_list ap)
 	return builtin_vfprintf(stdout, format, ap);
 }
 
+#ifdef WIN32
+/**
+ * Set TTY color on Windows consoles
+ */
+static void set_console_color(HANDLE handle, int color)
+{
+	CONSOLE_SCREEN_BUFFER_INFO info;
+	struct {
+		/* escape code */
+		int color;
+		/* windows console color combination */
+		WORD attributes;
+	} maps[] = {
+		{ 30,	0															},
+		{ 31,	FOREGROUND_RED 												},
+		{ 32,	FOREGROUND_GREEN											},
+		{ 33,	FOREGROUND_GREEN | FOREGROUND_RED							},
+		{ 34,	FOREGROUND_BLUE | FOREGROUND_INTENSITY						},
+		{ 35,	FOREGROUND_RED | FOREGROUND_BLUE							},
+		{ 36,	FOREGROUND_GREEN | FOREGROUND_BLUE							},
+		{ 37,	FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED			},
+		{ 39,	FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED			},
+		{ 40,	0															},
+		{ 41,	BACKGROUND_RED												},
+		{ 42,	BACKGROUND_GREEN											},
+		{ 43,	BACKGROUND_GREEN | BACKGROUND_RED							},
+		{ 44,	BACKGROUND_BLUE												},
+		{ 45,	BACKGROUND_RED | BACKGROUND_BLUE							},
+		{ 46,	BACKGROUND_GREEN | BACKGROUND_BLUE							},
+		{ 47,	BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED			},
+		{ 49,	0															},
+	};
+	int i;
+
+	if (GetConsoleScreenBufferInfo(handle, &info))
+	{
+		if (color < 40)
+		{
+			info.wAttributes &= ~(FOREGROUND_BLUE | FOREGROUND_GREEN |
+								  FOREGROUND_RED | FOREGROUND_INTENSITY);
+		}
+		else
+		{
+			info.wAttributes &= ~(BACKGROUND_BLUE | BACKGROUND_GREEN |
+								  BACKGROUND_RED | BACKGROUND_INTENSITY);
+		}
+		for (i = 0; i < countof(maps); i++)
+		{
+			if (maps[i].color == color)
+			{
+				info.wAttributes |= maps[i].attributes;
+				SetConsoleTextAttribute(handle, info.wAttributes);
+				break;
+			}
+		}
+	}
+}
+
+int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
+{
+	char buf[PRINTF_BUF_LEN], *pos, *stop;
+	HANDLE handle;
+	int len, total;
+	DWORD clen, mode;
+
+	total = len = builtin_vsnprintf(buf, sizeof(buf), format, ap);
+	switch (fileno(stream))
+	{
+		case 1:
+			handle = GetStdHandle(STD_OUTPUT_HANDLE);
+			break;
+		case 2:
+			handle = GetStdHandle(STD_ERROR_HANDLE);
+			break;
+		default:
+			handle = INVALID_HANDLE_VALUE;
+			break;
+	}
+	/* GetConsoleMode fails if output redirected */
+	if (handle == INVALID_HANDLE_VALUE || !GetConsoleMode(handle, &mode))
+	{
+		return fwrite(buf, 1, len, stream);
+	}
+	while (len)
+	{
+		pos = &buf[total - len];
+		if (len > 4)
+		{
+			if (pos[0] == '\e' && pos[1] == '[' && pos[4] == 'm')
+			{
+				if (isdigit(pos[3]))
+				{
+					if (pos[2] == '3' || pos[2] == '4')
+					{
+						set_console_color(handle,
+									(pos[2] - '0') * 10 + pos[3] - '0');
+						len -= 5;
+						continue;
+					}
+				}
+			}
+		}
+		stop = memchr(pos + 1, '\e', len);
+		if (stop)
+		{
+			clen = stop - pos;
+		}
+		else
+		{
+			clen = len;
+		}
+		if (clen && !WriteConsole(handle, pos, clen, &clen, NULL))
+		{
+			break;
+		}
+		len -= clen;
+	}
+	return total - len;
+}
+
+#else /* !WIN32 */
+
 int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
 {
 	char buf[PRINTF_BUF_LEN];
@@ -1113,6 +1235,8 @@ int builtin_vfprintf(FILE *stream, const char *format, va_list ap)
 	return fwrite(buf, 1, len, stream);
 }
 
+#endif /* !WIN32 */
+
 int builtin_vsprintf(char *str, const char *format, va_list ap)
 {
 	return builtin_vsnprintf(str, ~(size_t)0, format, ap);
diff --git a/src/libstrongswan/utils/settings.c b/src/libstrongswan/utils/settings.c
deleted file mode 100644
index cf34fd1..0000000
--- a/src/libstrongswan/utils/settings.c
+++ /dev/null
@@ -1,1520 +0,0 @@
-/*
- * Copyright (C) 2010-2014 Tobias Brunner
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#define _GNU_SOURCE
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#ifdef HAVE_GLOB_H
-#include <glob.h>
-#endif /* HAVE_GLOB_H */
-
-#include "settings.h"
-
-#include "collections/array.h"
-#include "collections/hashtable.h"
-#include "collections/linked_list.h"
-#include "threading/rwlock.h"
-#include "utils/debug.h"
-
-#define MAX_INCLUSION_LEVEL		10
-
-typedef struct private_settings_t private_settings_t;
-typedef struct section_t section_t;
-typedef struct kv_t kv_t;
-
-/**
- * private data of settings
- */
-struct private_settings_t {
-
-	/**
-	 * public functions
-	 */
-	settings_t public;
-
-	/**
-	 * top level section
-	 */
-	section_t *top;
-
-	/**
-	 * contents of loaded files and in-memory settings (char*)
-	 */
-	linked_list_t *contents;
-
-	/**
-	 * lock to safely access the settings
-	 */
-	rwlock_t *lock;
-};
-
-/**
- * section containing subsections and key value pairs
- */
-struct section_t {
-
-	/**
-	 * name of the section
-	 */
-	char *name;
-
-	/**
-	 * fallback sections, as section_t
-	 */
-	array_t *fallbacks;
-
-	/**
-	 * subsections, as section_t
-	 */
-	array_t *sections;
-
-	/**
-	 * key value pairs, as kv_t
-	 */
-	array_t *kv;
-};
-
-/**
- * Key value pair
- */
-struct kv_t {
-
-	/**
-	 * key string, relative
-	 */
-	char *key;
-
-	/**
-	 * value as string
-	 */
-	char *value;
-};
-
-/**
- * create a key/value pair
- */
-static kv_t *kv_create(char *key, char *value)
-{
-	kv_t *this;
-	INIT(this,
-		.key = strdup(key),
-		.value = value,
-	);
-	return this;
-}
-
-/**
- * destroy a key/value pair
- */
-static void kv_destroy(kv_t *this)
-{
-	free(this->key);
-	free(this);
-}
-
-/**
- * create a section with the given name
- */
-static section_t *section_create(char *name)
-{
-	section_t *this;
-	INIT(this,
-		.name = strdupnull(name),
-	);
-	return this;
-}
-
-/**
- * destroy a section
- */
-static void section_destroy(section_t *this)
-{
-	array_destroy_function(this->sections, (void*)section_destroy, NULL);
-	array_destroy_function(this->kv, (void*)kv_destroy, NULL);
-	array_destroy(this->fallbacks);
-	free(this->name);
-	free(this);
-}
-
-/**
- * Purge contents of a section, returns if section can be safely removed.
- */
-static bool section_purge(section_t *this)
-{
-	section_t *current;
-	int i;
-
-	array_destroy_function(this->kv, (void*)kv_destroy, NULL);
-	this->kv = NULL;
-	/* we ensure sections used as fallback, or configured with fallbacks (or
-	 * having any such subsections) are not removed */
-	for (i = array_count(this->sections) - 1; i >= 0; i--)
-	{
-		array_get(this->sections, i, &current);
-		if (section_purge(current))
-		{
-			array_remove(this->sections, i, NULL);
-			section_destroy(current);
-		}
-	}
-	return !this->fallbacks && !array_count(this->sections);
-}
-
-/**
- * callback to find a section by name
- */
-static int section_find(const void *a, const void *b)
-{
-	const char *key = a;
-	const section_t *item = b;
-	return strcmp(key, item->name);
-}
-
-/**
- * callback to sort sections by name
- */
-static int section_sort(const void *a, const void *b, void *user)
-{
-	const section_t *sa = a, *sb = b;
-	return strcmp(sa->name, sb->name);
-}
-
-/**
- * callback to find a kv pair by key
- */
-static int kv_find(const void *a, const void *b)
-{
-	const char *key = a;
-	const kv_t *item = b;
-	return strcmp(key, item->key);
-}
-
-/**
- * callback to sort kv pairs by key
- */
-static int kv_sort(const void *a, const void *b, void *user)
-{
-	const kv_t *kva = a, *kvb = b;
-	return strcmp(kva->key, kvb->key);
-}
-
-/**
- * Print a format key, but consume already processed arguments
- */
-static bool print_key(char *buf, int len, char *start, char *key, va_list args)
-{
-	va_list copy;
-	char *pos = start;
-	bool res;
-
-	va_copy(copy, args);
-	while (TRUE)
-	{
-		pos = memchr(pos, '%', key - pos);
-		if (!pos)
-		{
-			break;
-		}
-		pos++;
-		switch (*pos)
-		{
-			case 'd':
-				va_arg(copy, int);
-				break;
-			case 's':
-				va_arg(copy, char*);
-				break;
-			case 'N':
-				va_arg(copy, enum_name_t*);
-				va_arg(copy, int);
-				break;
-			case '%':
-				break;
-			default:
-				DBG1(DBG_CFG, "settings with %%%c not supported!", *pos);
-				break;
-		}
-		pos++;
-	}
-	res = vsnprintf(buf, len, key, copy) < len;
-	va_end(copy);
-	return res;
-}
-
-/**
- * Find a section by a given key, using buffered key, reusable buffer.
- * If "ensure" is TRUE, the sections are created if they don't exist.
- */
-static section_t *find_section_buffered(section_t *section,
-					char *start, char *key, va_list args, char *buf, int len,
-					bool ensure)
-{
-	char *pos;
-	section_t *found = NULL;
-
-	if (section == NULL)
-	{
-		return NULL;
-	}
-	pos = strchr(key, '.');
-	if (pos)
-	{
-		*pos = '\0';
-		pos++;
-	}
-	if (!print_key(buf, len, start, key, args))
-	{
-		return NULL;
-	}
-	if (!strlen(buf))
-	{
-		found = section;
-	}
-	else if (array_bsearch(section->sections, buf, section_find, &found) == -1)
-	{
-		if (ensure)
-		{
-			found = section_create(buf);
-			array_insert_create(&section->sections, ARRAY_TAIL, found);
-			array_sort(section->sections, section_sort, NULL);
-		}
-	}
-	if (found && pos)
-	{
-		return find_section_buffered(found, start, pos, args, buf, len, ensure);
-	}
-	return found;
-}
-
-/**
- * Find all sections via a given key considering fallbacks, using buffered key,
- * reusable buffer.
- */
-static void find_sections_buffered(section_t *section, char *start, char *key,
-						va_list args, char *buf, int len, array_t **sections)
-{
-	section_t *found = NULL, *fallback;
-	char *pos;
-	int i;
-
-	if (!section)
-	{
-		return;
-	}
-	pos = strchr(key, '.');
-	if (pos)
-	{
-		*pos = '\0';
-	}
-	if (!print_key(buf, len, start, key, args))
-	{
-		return;
-	}
-	if (pos)
-	{	/* restore so we can follow fallbacks */
-		*pos = '.';
-	}
-	if (!strlen(buf))
-	{
-		found = section;
-	}
-	else
-	{
-		array_bsearch(section->sections, buf, section_find, &found);
-	}
-	if (found)
-	{
-		if (pos)
-		{
-			find_sections_buffered(found, start, pos+1, args, buf, len,
-								   sections);
-		}
-		else
-		{
-			array_insert_create(sections, ARRAY_TAIL, found);
-			for (i = 0; i < array_count(found->fallbacks); i++)
-			{
-				array_get(found->fallbacks, i, &fallback);
-				array_insert_create(sections, ARRAY_TAIL, fallback);
-			}
-		}
-	}
-	if (section->fallbacks)
-	{
-		for (i = 0; i < array_count(section->fallbacks); i++)
-		{
-			array_get(section->fallbacks, i, &fallback);
-			find_sections_buffered(fallback, start, key, args, buf, len,
-								   sections);
-		}
-	}
-}
-
-/**
- * Ensure that the section with the given key exists (thread-safe).
- */
-static section_t *ensure_section(private_settings_t *this, section_t *section,
-								 const char *key, va_list args)
-{
-	char buf[128], keybuf[512];
-	section_t *found;
-
-	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
-	{
-		return NULL;
-	}
-	/* we might have to change the tree */
-	this->lock->write_lock(this->lock);
-	found = find_section_buffered(section, keybuf, keybuf, args, buf,
-								  sizeof(buf), TRUE);
-	this->lock->unlock(this->lock);
-	return found;
-}
-
-/**
- * Find a section by a given key with its fallbacks (not thread-safe!).
- * Sections are returned in depth-first order (array is allocated). NULL is
- * returned if no sections are found.
- */
-static array_t *find_sections(private_settings_t *this, section_t *section,
-							  char *key, va_list args)
-{
-	char buf[128], keybuf[512];
-	array_t *sections = NULL;
-
-	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
-	{
-		return NULL;
-	}
-	find_sections_buffered(section, keybuf, keybuf, args, buf,
-						   sizeof(buf), &sections);
-	return sections;
-}
-
-/**
- * Check if the given fallback section already exists
- */
-static bool fallback_exists(section_t *section, section_t *fallback)
-{
-	if (section == fallback)
-	{
-		return TRUE;
-	}
-	else if (section->fallbacks)
-	{
-		section_t *existing;
-		int i;
-
-		for (i = 0; i < array_count(section->fallbacks); i++)
-		{
-			array_get(section->fallbacks, i, &existing);
-			if (existing == fallback)
-			{
-				return TRUE;
-			}
-		}
-	}
-	return FALSE;
-}
-
-/**
- * Ensure that the section with the given key exists and add the given fallback
- * section (thread-safe).
- */
-static void add_fallback_to_section(private_settings_t *this,
-							section_t *section, const char *key, va_list args,
-							section_t *fallback)
-{
-	char buf[128], keybuf[512];
-	section_t *found;
-
-	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
-	{
-		return;
-	}
-	this->lock->write_lock(this->lock);
-	found = find_section_buffered(section, keybuf, keybuf, args, buf,
-								  sizeof(buf), TRUE);
-	if (!fallback_exists(found, fallback))
-	{
-		/* to ensure sections referred to as fallback are not purged, we create
-		 * the array there too */
-		if (!fallback->fallbacks)
-		{
-			fallback->fallbacks = array_create(0, 0);
-		}
-		array_insert_create(&found->fallbacks, ARRAY_TAIL, fallback);
-	}
-	this->lock->unlock(this->lock);
-}
-
-/**
- * Find the key/value pair for a key, using buffered key, reusable buffer
- * If "ensure" is TRUE, the sections (and key/value pair) are created if they
- * don't exist.
- * Fallbacks are only considered if "ensure" is FALSE.
- */
-static kv_t *find_value_buffered(section_t *section, char *start, char *key,
-								 va_list args, char *buf, int len, bool ensure)
-{
-	int i;
-	char *pos;
-	kv_t *kv = NULL;
-	section_t *found = NULL;
-
-	if (section == NULL)
-	{
-		return NULL;
-	}
-
-	pos = strchr(key, '.');
-	if (pos)
-	{
-		*pos = '\0';
-		if (!print_key(buf, len, start, key, args))
-		{
-			return NULL;
-		}
-		/* restore so we can retry for fallbacks */
-		*pos = '.';
-		if (!strlen(buf))
-		{
-			found = section;
-		}
-		else if (array_bsearch(section->sections, buf, section_find,
-							   &found) == -1)
-		{
-			if (ensure)
-			{
-				found = section_create(buf);
-				array_insert_create(&section->sections, ARRAY_TAIL, found);
-				array_sort(section->sections, section_sort, NULL);
-			}
-		}
-		if (found)
-		{
-			kv = find_value_buffered(found, start, pos+1, args, buf, len,
-									 ensure);
-		}
-		if (!kv && !ensure && section->fallbacks)
-		{
-			for (i = 0; !kv && i < array_count(section->fallbacks); i++)
-			{
-				array_get(section->fallbacks, i, &found);
-				kv = find_value_buffered(found, start, key, args, buf, len,
-										 ensure);
-			}
-		}
-	}
-	else
-	{
-		if (!print_key(buf, len, start, key, args))
-		{
-			return NULL;
-		}
-		if (array_bsearch(section->kv, buf, kv_find, &kv) == -1)
-		{
-			if (ensure)
-			{
-				kv = kv_create(buf, NULL);
-				array_insert_create(&section->kv, ARRAY_TAIL, kv);
-				array_sort(section->kv, kv_sort, NULL);
-			}
-			else if (section->fallbacks)
-			{
-				for (i = 0; !kv && i < array_count(section->fallbacks); i++)
-				{
-					array_get(section->fallbacks, i, &found);
-					kv = find_value_buffered(found, start, key, args, buf, len,
-											 ensure);
-				}
-			}
-		}
-	}
-	return kv;
-}
-
-/**
- * Find the string value for a key (thread-safe).
- */
-static char *find_value(private_settings_t *this, section_t *section,
-						char *key, va_list args)
-{
-	char buf[128], keybuf[512], *value = NULL;
-	kv_t *kv;
-
-	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
-	{
-		return NULL;
-	}
-	this->lock->read_lock(this->lock);
-	kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
-							 FALSE);
-	if (kv)
-	{
-		value = kv->value;
-	}
-	this->lock->unlock(this->lock);
-	return value;
-}
-
-/**
- * Set a value to a copy of the given string (thread-safe).
- */
-static void set_value(private_settings_t *this, section_t *section,
-					  char *key, va_list args, char *value)
-{
-	char buf[128], keybuf[512];
-	kv_t *kv;
-
-	if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
-	{
-		return;
-	}
-	this->lock->write_lock(this->lock);
-	kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
-							 TRUE);
-	if (kv)
-	{
-		if (!value)
-		{
-			kv->value = NULL;
-		}
-		else if (kv->value && (strlen(value) <= strlen(kv->value)))
-		{	/* overwrite in-place, if possible */
-			strcpy(kv->value, value);
-		}
-		else
-		{	/* otherwise clone the string and store it in the cache */
-			kv->value = strdup(value);
-			this->contents->insert_last(this->contents, kv->value);
-		}
-	}
-	this->lock->unlock(this->lock);
-}
-
-METHOD(settings_t, get_str, char*,
-	private_settings_t *this, char *key, char *def, ...)
-{
-	char *value;
-	va_list args;
-
-	va_start(args, def);
-	value = find_value(this, this->top, key, args);
-	va_end(args);
-	if (value)
-	{
-		return value;
-	}
-	return def;
-}
-
-/**
- * Described in header
- */
-inline bool settings_value_as_bool(char *value, bool def)
-{
-	if (value)
-	{
-		if (strcaseeq(value, "1") ||
-			strcaseeq(value, "yes") ||
-			strcaseeq(value, "true") ||
-			strcaseeq(value, "enabled"))
-		{
-			return TRUE;
-		}
-		else if (strcaseeq(value, "0") ||
-				 strcaseeq(value, "no") ||
-				 strcaseeq(value, "false") ||
-				 strcaseeq(value, "disabled"))
-		{
-			return FALSE;
-		}
-	}
-	return def;
-}
-
-METHOD(settings_t, get_bool, bool,
-	private_settings_t *this, char *key, bool def, ...)
-{
-	char *value;
-	va_list args;
-
-	va_start(args, def);
-	value = find_value(this, this->top, key, args);
-	va_end(args);
-	return settings_value_as_bool(value, def);
-}
-
-/**
- * Described in header
- */
-inline int settings_value_as_int(char *value, int def)
-{
-	int intval;
-	if (value)
-	{
-		errno = 0;
-		intval = strtol(value, NULL, 10);
-		if (errno == 0)
-		{
-			return intval;
-		}
-	}
-	return def;
-}
-
-METHOD(settings_t, get_int, int,
-	private_settings_t *this, char *key, int def, ...)
-{
-	char *value;
-	va_list args;
-
-	va_start(args, def);
-	value = find_value(this, this->top, key, args);
-	va_end(args);
-	return settings_value_as_int(value, def);
-}
-
-/**
- * Described in header
- */
-inline double settings_value_as_double(char *value, double def)
-{
-	double dval;
-	if (value)
-	{
-		errno = 0;
-		dval = strtod(value, NULL);
-		if (errno == 0)
-		{
-			return dval;
-		}
-	}
-	return def;
-}
-
-METHOD(settings_t, get_double, double,
-	private_settings_t *this, char *key, double def, ...)
-{
-	char *value;
-	va_list args;
-
-	va_start(args, def);
-	value = find_value(this, this->top, key, args);
-	va_end(args);
-	return settings_value_as_double(value, def);
-}
-
-/**
- * Described in header
- */
-inline u_int32_t settings_value_as_time(char *value, u_int32_t def)
-{
-	char *endptr;
-	u_int32_t timeval;
-	if (value)
-	{
-		errno = 0;
-		timeval = strtoul(value, &endptr, 10);
-		if (errno == 0)
-		{
-			switch (*endptr)
-			{
-				case 'd':		/* time in days */
-					timeval *= 24 * 3600;
-					break;
-				case 'h':		/* time in hours */
-					timeval *= 3600;
-					break;
-				case 'm':		/* time in minutes */
-					timeval *= 60;
-					break;
-				case 's':		/* time in seconds */
-				default:
-					break;
-			}
-			return timeval;
-		}
-	}
-	return def;
-}
-
-METHOD(settings_t, get_time, u_int32_t,
-	private_settings_t *this, char *key, u_int32_t def, ...)
-{
-	char *value;
-	va_list args;
-
-	va_start(args, def);
-	value = find_value(this, this->top, key, args);
-	va_end(args);
-	return settings_value_as_time(value, def);
-}
-
-METHOD(settings_t, set_str, void,
-	private_settings_t *this, char *key, char *value, ...)
-{
-	va_list args;
-	va_start(args, value);
-	set_value(this, this->top, key, args, value);
-	va_end(args);
-}
-
-METHOD(settings_t, set_bool, void,
-	private_settings_t *this, char *key, bool value, ...)
-{
-	va_list args;
-	va_start(args, value);
-	set_value(this, this->top, key, args, value ? "1" : "0");
-	va_end(args);
-}
-
-METHOD(settings_t, set_int, void,
-	private_settings_t *this, char *key, int value, ...)
-{
-	char val[16];
-	va_list args;
-	va_start(args, value);
-	if (snprintf(val, sizeof(val), "%d", value) < sizeof(val))
-	{
-		set_value(this, this->top, key, args, val);
-	}
-	va_end(args);
-}
-
-METHOD(settings_t, set_double, void,
-	private_settings_t *this, char *key, double value, ...)
-{
-	char val[64];
-	va_list args;
-	va_start(args, value);
-	if (snprintf(val, sizeof(val), "%f", value) < sizeof(val))
-	{
-		set_value(this, this->top, key, args, val);
-	}
-	va_end(args);
-}
-
-METHOD(settings_t, set_time, void,
-	private_settings_t *this, char *key, u_int32_t value, ...)
-{
-	char val[16];
-	va_list args;
-	va_start(args, value);
-	if (snprintf(val, sizeof(val), "%u", value) < sizeof(val))
-	{
-		set_value(this, this->top, key, args, val);
-	}
-	va_end(args);
-}
-
-METHOD(settings_t, set_default_str, bool,
-	private_settings_t *this, char *key, char *value, ...)
-{
-	char *old;
-	va_list args;
-
-	va_start(args, value);
-	old = find_value(this, this->top, key, args);
-	va_end(args);
-
-	if (!old)
-	{
-		va_start(args, value);
-		set_value(this, this->top, key, args, value);
-		va_end(args);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/**
- * Data for enumerators
- */
-typedef struct {
-	/** settings_t instance */
-	private_settings_t *settings;
-	/** sections to enumerate */
-	array_t *sections;
-	/** sections/keys that were already enumerated */
-	hashtable_t *seen;
-} enumerator_data_t;
-
-/**
- * Destroy enumerator data
- */
-static void enumerator_destroy(enumerator_data_t *this)
-{
-	this->settings->lock->unlock(this->settings->lock);
-	this->seen->destroy(this->seen);
-	array_destroy(this->sections);
-	free(this);
-}
-
-/**
- * Enumerate section names, not sections
- */
-static bool section_filter(hashtable_t *seen, section_t **in, char **out)
-{
-	*out = (*in)->name;
-	if (seen->get(seen, *out))
-	{
-		return FALSE;
-	}
-	seen->put(seen, *out, *out);
-	return TRUE;
-}
-
-/**
- * Enumerate sections of the given section
- */
-static enumerator_t *section_enumerator(section_t *section,
-										enumerator_data_t *data)
-{
-	return enumerator_create_filter(array_create_enumerator(section->sections),
-				(void*)section_filter, data->seen, NULL);
-}
-
-METHOD(settings_t, create_section_enumerator, enumerator_t*,
-	private_settings_t *this, char *key, ...)
-{
-	enumerator_data_t *data;
-	array_t *sections;
-	va_list args;
-
-	this->lock->read_lock(this->lock);
-	va_start(args, key);
-	sections = find_sections(this, this->top, key, args);
-	va_end(args);
-
-	if (!sections)
-	{
-		this->lock->unlock(this->lock);
-		return enumerator_create_empty();
-	}
-	INIT(data,
-		.settings = this,
-		.sections = sections,
-		.seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
-	);
-	return enumerator_create_nested(array_create_enumerator(sections),
-					(void*)section_enumerator, data, (void*)enumerator_destroy);
-}
-
-/**
- * Enumerate key and values, not kv_t entries
- */
-static bool kv_filter(hashtable_t *seen, kv_t **in, char **key,
-					  void *none, char **value)
-{
-	*key = (*in)->key;
-	if (seen->get(seen, *key))
-	{
-		return FALSE;
-	}
-	*value = (*in)->value;
-	seen->put(seen, *key, *key);
-	return TRUE;
-}
-
-/**
- * Enumerate key/value pairs of the given section
- */
-static enumerator_t *kv_enumerator(section_t *section, enumerator_data_t *data)
-{
-	return enumerator_create_filter(array_create_enumerator(section->kv),
-					(void*)kv_filter, data->seen, NULL);
-}
-
-METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
-	private_settings_t *this, char *key, ...)
-{
-	enumerator_data_t *data;
-	array_t *sections;
-	va_list args;
-
-	this->lock->read_lock(this->lock);
-	va_start(args, key);
-	sections = find_sections(this, this->top, key, args);
-	va_end(args);
-
-	if (!sections)
-	{
-		this->lock->unlock(this->lock);
-		return enumerator_create_empty();
-	}
-	INIT(data,
-		.settings = this,
-		.sections = sections,
-		.seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
-	);
-	return enumerator_create_nested(array_create_enumerator(sections),
-					(void*)kv_enumerator, data, (void*)enumerator_destroy);
-}
-
-METHOD(settings_t, add_fallback, void,
-	private_settings_t *this, const char *key, const char *fallback, ...)
-{
-	section_t *section;
-	va_list args;
-
-	/* find/create the fallback */
-	va_start(args, fallback);
-	section = ensure_section(this, this->top, fallback, args);
-	va_end(args);
-
-	va_start(args, fallback);
-	add_fallback_to_section(this, this->top, key, args, section);
-	va_end(args);
-}
-
-/**
- * parse text, truncate "skip" chars, delimited by term respecting brackets.
- *
- * Chars in "skip" are truncated at the beginning and the end of the resulting
- * token. "term" contains a list of characters to read up to (first match),
- * while "br" contains bracket counterparts found in "term" to skip.
- */
-static char parse(char **text, char *skip, char *term, char *br, char **token)
-{
-	char *best = NULL;
-	char best_term = '\0';
-
-	/* skip leading chars */
-	while (strchr(skip, **text))
-	{
-		(*text)++;
-		if (!**text)
-		{
-			return 0;
-		}
-	}
-	/* mark begin of subtext */
-	*token = *text;
-	while (*term)
-	{
-		char *pos = *text;
-		int level = 1;
-
-		/* find terminator */
-		while (*pos)
-		{
-			if (*pos == *term)
-			{
-				level--;
-			}
-			else if (br && *pos == *br)
-			{
-				level++;
-			}
-			if (level == 0)
-			{
-				if (best == NULL || best > pos)
-				{
-					best = pos;
-					best_term = *term;
-				}
-				break;
-			}
-			pos++;
-		}
-		/* try next terminator */
-		term++;
-		if (br)
-		{
-			br++;
-		}
-	}
-	if (best)
-	{
-		/* update input */
-		*text = best;
-		/* null trailing bytes */
-		do
-		{
-			*best = '\0';
-			best--;
-		}
-		while (best >= *token && strchr(skip, *best));
-		/* return found terminator */
-		return best_term;
-	}
-	return 0;
-}
-
-/**
- * Check if "text" starts with "pattern".
- * Characters in "skip" are skipped first. If found, TRUE is returned and "text"
- * is modified to point to the character right after "pattern".
- */
-static bool starts_with(char **text, char *skip, char *pattern)
-{
-	char *pos = *text;
-	int len = strlen(pattern);
-	while (strchr(skip, *pos))
-	{
-		pos++;
-		if (!*pos)
-		{
-			return FALSE;
-		}
-	}
-	if (strlen(pos) < len || !strneq(pos, pattern, len))
-	{
-		return FALSE;
-	}
-	*text = pos + len;
-	return TRUE;
-}
-
-/**
- * Check if what follows in "text" is an include statement.
- * If this function returns TRUE, "text" will point to the character right after
- * the include pattern, which is returned in "pattern".
- */
-static bool parse_include(char **text, char **pattern)
-{
-	char *pos = *text;
-	if (!starts_with(&pos, "\n\t ", "include"))
-	{
-		return FALSE;
-	}
-	if (starts_with(&pos, "\t ", "="))
-	{	/* ignore "include = value" */
-		return FALSE;
-	}
-	*text = pos;
-	return parse(text, "\t ", "\n", NULL, pattern) != 0;
-}
-
-/**
- * Forward declaration.
- */
-static bool parse_files(linked_list_t *contents, char *file, int level,
-						char *pattern, section_t *section);
-
-/**
- * Parse a section
- */
-static bool parse_section(linked_list_t *contents, char *file, int level,
-						  char **text, section_t *section)
-{
-	bool finished = FALSE;
-	char *key, *value, *inner;
-
-	while (!finished)
-	{
-		if (parse_include(text, &value))
-		{
-			if (!parse_files(contents, file, level, value, section))
-			{
-				DBG1(DBG_LIB, "failed to include '%s'", value);
-				return FALSE;
-			}
-			continue;
-		}
-		switch (parse(text, "\t\n ", "{=#", NULL, &key))
-		{
-			case '{':
-				if (parse(text, "\t ", "}", "{", &inner))
-				{
-					section_t *sub;
-					if (!strlen(key))
-					{
-						DBG1(DBG_LIB, "skipping section without name in '%s'",
-							 section->name);
-						continue;
-					}
-					if (array_bsearch(section->sections, key, section_find,
-									  &sub) == -1)
-					{
-						sub = section_create(key);
-						if (parse_section(contents, file, level, &inner, sub))
-						{
-							array_insert_create(&section->sections, ARRAY_TAIL,
-												sub);
-							array_sort(section->sections, section_sort, NULL);
-							continue;
-						}
-						section_destroy(sub);
-					}
-					else
-					{	/* extend the existing section */
-						if (parse_section(contents, file, level, &inner, sub))
-						{
-							continue;
-						}
-					}
-					DBG1(DBG_LIB, "parsing subsection '%s' failed", key);
-					break;
-				}
-				DBG1(DBG_LIB, "matching '}' not found near %s", *text);
-				break;
-			case '=':
-				if (parse(text, "\t ", "\n", NULL, &value))
-				{
-					kv_t *kv;
-					if (!strlen(key))
-					{
-						DBG1(DBG_LIB, "skipping value without key in '%s'",
-							 section->name);
-						continue;
-					}
-					if (array_bsearch(section->kv, key, kv_find, &kv) == -1)
-					{
-						kv = kv_create(key, value);
-						array_insert_create(&section->kv, ARRAY_TAIL, kv);
-						array_sort(section->kv, kv_sort, NULL);
-					}
-					else
-					{	/* replace with the most recently read value */
-						kv->value = value;
-					}
-					continue;
-				}
-				DBG1(DBG_LIB, "parsing value failed near %s", *text);
-				break;
-			case '#':
-				parse(text, "", "\n", NULL, &value);
-				continue;
-			default:
-				finished = TRUE;
-				continue;
-		}
-		return FALSE;
-	}
-	return TRUE;
-}
-
-/**
- * Parse a file and add the settings to the given section.
- */
-static bool parse_file(linked_list_t *contents, char *file, int level,
-					   section_t *section)
-{
-	bool success;
-	char *text, *pos;
-	struct stat st;
-	FILE *fd;
-	int len;
-
-	DBG2(DBG_LIB, "loading config file '%s'", file);
-	if (stat(file, &st) == -1)
-	{
-		if (errno == ENOENT)
-		{
-#ifdef STRONGSWAN_CONF
-			if (streq(file, STRONGSWAN_CONF))
-			{
-				DBG2(DBG_LIB, "'%s' does not exist, ignored", file);
-			}
-			else
-#endif
-			{
-				DBG1(DBG_LIB, "'%s' does not exist, ignored", file);
-			}
-			return TRUE;
-		}
-		DBG1(DBG_LIB, "failed to stat '%s': %s", file, strerror(errno));
-		return FALSE;
-	}
-	else if (!S_ISREG(st.st_mode))
-	{
-		DBG1(DBG_LIB, "'%s' is not a regular file", file);
-		return FALSE;
-	}
-	fd = fopen(file, "r");
-	if (fd == NULL)
-	{
-		DBG1(DBG_LIB, "'%s' is not readable", file);
-		return FALSE;
-	}
-	fseek(fd, 0, SEEK_END);
-	len = ftell(fd);
-	rewind(fd);
-	text = malloc(len + 2);
-	text[len] = text[len + 1] = '\0';
-	if (fread(text, 1, len, fd) != len)
-	{
-		free(text);
-		fclose(fd);
-		return FALSE;
-	}
-	fclose(fd);
-
-	pos = text;
-	success = parse_section(contents, file, level, &pos, section);
-	if (!success)
-	{
-		free(text);
-	}
-	else
-	{
-		contents->insert_last(contents, text);
-	}
-	return success;
-}
-
-/**
- * Load the files matching "pattern", which is resolved with glob(3), if
- * available.
- * If the pattern is relative, the directory of "file" is used as base.
- */
-static bool parse_files(linked_list_t *contents, char *file, int level,
-						char *pattern, section_t *section)
-{
-	bool success = TRUE;
-	char pat[PATH_MAX];
-
-	if (level > MAX_INCLUSION_LEVEL)
-	{
-		DBG1(DBG_LIB, "maximum level of %d includes reached, ignored",
-			 MAX_INCLUSION_LEVEL);
-		return TRUE;
-	}
-
-	if (!strlen(pattern))
-	{
-		DBG1(DBG_LIB, "empty include pattern, ignored");
-		return TRUE;
-	}
-
-	if (!file || pattern[0] == '/')
-	{	/* absolute path */
-		if (snprintf(pat, sizeof(pat), "%s", pattern) >= sizeof(pat))
-		{
-			DBG1(DBG_LIB, "include pattern too long, ignored");
-			return TRUE;
-		}
-	}
-	else
-	{	/* base relative paths to the directory of the current file */
-		char *dir = path_dirname(file);
-		if (snprintf(pat, sizeof(pat), "%s/%s", dir, pattern) >= sizeof(pat))
-		{
-			DBG1(DBG_LIB, "include pattern too long, ignored");
-			free(dir);
-			return TRUE;
-		}
-		free(dir);
-	}
-#ifdef HAVE_GLOB_H
-	{
-		int status;
-		glob_t buf;
-
-		status = glob(pat, GLOB_ERR, NULL, &buf);
-		if (status == GLOB_NOMATCH)
-		{
-			DBG1(DBG_LIB, "no files found matching '%s', ignored", pat);
-		}
-		else if (status != 0)
-		{
-			DBG1(DBG_LIB, "expanding file pattern '%s' failed", pat);
-			success = FALSE;
-		}
-		else
-		{
-			char **expanded;
-			for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
-			{
-				success &= parse_file(contents, *expanded, level + 1, section);
-				if (!success)
-				{
-					break;
-				}
-			}
-		}
-		globfree(&buf);
-	}
-#else /* HAVE_GLOB_H */
-	/* if glob(3) is not available, try to load pattern directly */
-	success = parse_file(contents, pat, level + 1, section);
-#endif /* HAVE_GLOB_H */
-	return success;
-}
-
-/**
- * Recursivly extends "base" with "extension".
- */
-static void section_extend(section_t *base, section_t *extension)
-{
-	enumerator_t *enumerator;
-	section_t *sec;
-	kv_t *kv;
-
-	enumerator = array_create_enumerator(extension->sections);
-	while (enumerator->enumerate(enumerator, (void**)&sec))
-	{
-		section_t *found;
-		if (array_bsearch(base->sections, sec->name, section_find,
-			&found) != -1)
-		{
-			section_extend(found, sec);
-		}
-		else
-		{
-			array_remove_at(extension->sections, enumerator);
-			array_insert_create(&base->sections, ARRAY_TAIL, sec);
-			array_sort(base->sections, section_sort, NULL);
-		}
-	}
-	enumerator->destroy(enumerator);
-
-	enumerator = array_create_enumerator(extension->kv);
-	while (enumerator->enumerate(enumerator, (void**)&kv))
-	{
-		kv_t *found;
-		if (array_bsearch(base->kv, kv->key, kv_find, &found) != -1)
-		{
-			found->value = kv->value;
-		}
-		else
-		{
-			array_remove_at(extension->kv, enumerator);
-			array_insert_create(&base->kv, ARRAY_TAIL, kv);
-			array_sort(base->kv, kv_sort, NULL);
-		}
-	}
-	enumerator->destroy(enumerator);
-}
-
-/**
- * Load settings from files matching the given file pattern.
- * All sections and values are added relative to "parent".
- * All files (even included ones) have to be loaded successfully.
- */
-static bool load_files_internal(private_settings_t *this, section_t *parent,
-								char *pattern, bool merge)
-{
-	char *text;
-	linked_list_t *contents;
-	section_t *section;
-
-	if (pattern == NULL)
-	{
-#ifdef STRONGSWAN_CONF
-		pattern = STRONGSWAN_CONF;
-#else
-		return FALSE;
-#endif
-	}
-
-	contents = linked_list_create();
-	section = section_create(NULL);
-
-	if (!parse_files(contents, NULL, 0, pattern, section))
-	{
-		contents->destroy_function(contents, (void*)free);
-		section_destroy(section);
-		return FALSE;
-	}
-
-	this->lock->write_lock(this->lock);
-	if (!merge)
-	{
-		section_purge(parent);
-	}
-	/* extend parent section */
-	section_extend(parent, section);
-	/* move contents of loaded files to main store */
-	while (contents->remove_first(contents, (void**)&text) == SUCCESS)
-	{
-		this->contents->insert_last(this->contents, text);
-	}
-	this->lock->unlock(this->lock);
-
-	section_destroy(section);
-	contents->destroy(contents);
-	return TRUE;
-}
-
-METHOD(settings_t, load_files, bool,
-	private_settings_t *this, char *pattern, bool merge)
-{
-	return load_files_internal(this, this->top, pattern, merge);
-}
-
-METHOD(settings_t, load_files_section, bool,
-	private_settings_t *this, char *pattern, bool merge, char *key, ...)
-{
-	section_t *section;
-	va_list args;
-
-	va_start(args, key);
-	section = ensure_section(this, this->top, key, args);
-	va_end(args);
-
-	if (!section)
-	{
-		return FALSE;
-	}
-	return load_files_internal(this, section, pattern, merge);
-}
-
-METHOD(settings_t, destroy, void,
-	private_settings_t *this)
-{
-	section_destroy(this->top);
-	this->contents->destroy_function(this->contents, (void*)free);
-	this->lock->destroy(this->lock);
-	free(this);
-}
-
-/*
- * see header file
- */
-settings_t *settings_create(char *file)
-{
-	private_settings_t *this;
-
-	INIT(this,
-		.public = {
-			.get_str = _get_str,
-			.get_int = _get_int,
-			.get_double = _get_double,
-			.get_time = _get_time,
-			.get_bool = _get_bool,
-			.set_str = _set_str,
-			.set_int = _set_int,
-			.set_double = _set_double,
-			.set_time = _set_time,
-			.set_bool = _set_bool,
-			.set_default_str = _set_default_str,
-			.create_section_enumerator = _create_section_enumerator,
-			.create_key_value_enumerator = _create_key_value_enumerator,
-			.add_fallback = _add_fallback,
-			.load_files = _load_files,
-			.load_files_section = _load_files_section,
-			.destroy = _destroy,
-		},
-		.top = section_create(NULL),
-		.contents = linked_list_create(),
-		.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
-	);
-
-	load_files(this, file, FALSE);
-
-	return &this->public;
-}
diff --git a/src/libstrongswan/utils/settings.h b/src/libstrongswan/utils/settings.h
deleted file mode 100644
index 46403c4..0000000
--- a/src/libstrongswan/utils/settings.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup settings settings
- * @{ @ingroup utils
- */
-
-#ifndef SETTINGS_H_
-#define SETTINGS_H_
-
-typedef struct settings_t settings_t;
-
-#include "utils.h"
-#include "collections/enumerator.h"
-
-/**
- * Convert a string value returned by a key/value enumerator to a boolean.
- *
- * @see settings_t.create_key_value_enumerator()
- * @see settings_t.get_bool()
- * @param value			the string value
- * @param def			the default value, if value is NULL or invalid
- */
-bool settings_value_as_bool(char *value, bool def);
-
-/**
- * Convert a string value returned by a key/value enumerator to an integer.
- *
- * @see settings_t.create_key_value_enumerator()
- * @see settings_t.get_int()
- * @param value			the string value
- * @param def			the default value, if value is NULL or invalid
- */
-int settings_value_as_int(char *value, int def);
-
-/**
- * Convert a string value returned by a key/value enumerator to a double.
- *
- * @see settings_t.create_key_value_enumerator()
- * @see settings_t.get_double()
- * @param value			the string value
- * @param def			the default value, if value is NULL or invalid
- */
-double settings_value_as_double(char *value, double def);
-
-/**
- * Convert a string value returned by a key/value enumerator to a time value.
- *
- * @see settings_t.create_key_value_enumerator()
- * @see settings_t.get_time()
- * @param value			the string value
- * @param def			the default value, if value is NULL or invalid
- */
-u_int32_t settings_value_as_time(char *value, u_int32_t def);
-
-/**
- * Generic configuration options read from a config file.
- *
- * The syntax is quite simple:
- * @code
- * settings := (section|keyvalue)*
- * section  := name { settings }
- * keyvalue := key = value\n
- * @endcode
- * E.g.:
- * @code
-	a = b
-	section-one {
-		somevalue = asdf
-		subsection {
-			othervalue = xxx
-		}
-		yetanother = zz
-	}
-	section-two {
-	}
-	@endcode
- *
- * The values are accessed using the get() functions using dotted keys, e.g.
- *   section-one.subsection.othervalue
- *
- * Currently only a limited set of printf format specifiers are supported
- * (namely %s, %d and %N, see implementation for details).
- *
- * \section includes Including other files
- * Other files can be included, using the include statement e.g.
- * @code
- *   include /somepath/subconfig.conf
- * @endcode
- * Shell patterns like *.conf are possible.
- *
- * If the path is relative, the directory of the file containing the include
- * statement is used as base.
- *
- * Sections loaded from included files extend previously loaded sections,
- * already existing values are replaced.
- *
- * All settings included from files are added relative to the section the
- * include statement is in.
- *
- * The following files result in the same final config as above:
- *
- * @code
-	a = b
-	section-one {
-		somevalue = before include
-		include include.conf
-	}
-	include two.conf
-	@endcode
- * include.conf
- * @code
-	somevalue = asdf
-	subsection {
-		othervalue = yyy
-	}
-	yetanother = zz
-	@endcode
- * two.conf
- * @code
-	section-one {
-		subsection {
-			othervalue = xxx
-		}
-	}
-	section-two {
-	}
-	@endcode
- */
-struct settings_t {
-
-	/**
-	 * Get a settings value as a string.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param def		value returned if key not found
-	 * @param ...		argument list for key
-	 * @return			value pointing to internal string
-	 */
-	char* (*get_str)(settings_t *this, char *key, char *def, ...);
-
-	/**
-	 * Get a boolean yes|no, true|false value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param def		value returned if key not found
-	 * @param ...		argument list for key
-	 * @return			value of the key
-	 */
-	bool (*get_bool)(settings_t *this, char *key, bool def, ...);
-
-	/**
-	 * Get an integer value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param def		value returned if key not found
-	 * @param ...		argument list for key
-	 * @return			value of the key
-	 */
-	int (*get_int)(settings_t *this, char *key, int def, ...);
-
-	/**
-	 * Get an double value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param def		value returned if key not found
-	 * @param ...		argument list for key
-	 * @return			value of the key
-	 */
-	double (*get_double)(settings_t *this, char *key, double def, ...);
-
-	/**
-	 * Get a time value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param def		value returned if key not found
-	 * @param ...		argument list for key
-	 * @return			value of the key (in seconds)
-	 */
-	u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...);
-
-	/**
-	 * Set a string value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param value		value to set (gets cloned)
-	 * @param ...		argument list for key
-	 */
-	void (*set_str)(settings_t *this, char *key, char *value, ...);
-
-	/**
-	 * Set a boolean value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param value		value to set
-	 * @param ...		argument list for key
-	 */
-	void (*set_bool)(settings_t *this, char *key, bool value, ...);
-
-	/**
-	 * Set an integer value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param value		value to set
-	 * @param ...		argument list for key
-	 */
-	void (*set_int)(settings_t *this, char *key, int value, ...);
-
-	/**
-	 * Set an double value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param value		value to set
-	 * @param ...		argument list for key
-	 */
-	void (*set_double)(settings_t *this, char *key, double value, ...);
-
-	/**
-	 * Set a time value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param def		value to set
-	 * @param ...		argument list for key
-	 */
-	void (*set_time)(settings_t *this, char *key, u_int32_t value, ...);
-
-	/**
-	 * Set a default for string value.
-	 *
-	 * @param key		key including sections, printf style format
-	 * @param def		value to set if unconfigured
-	 * @param ...		argument list for key
-	 * @return			TRUE if a new default value for key has been set
-	 */
-	bool (*set_default_str)(settings_t *this, char *key, char *value, ...);
-
-	/**
-	 * Create an enumerator over subsection names of a section.
-	 *
-	 * @param section	section including parents, printf style format
-	 * @param ...		argument list for key
-	 * @return			enumerator over subsection names
-	 */
-	enumerator_t* (*create_section_enumerator)(settings_t *this,
-											   char *section, ...);
-
-	/**
-	 * Create an enumerator over key/value pairs in a section.
-	 *
-	 * @param section	section name to list key/value pairs of, printf style
-	 * @param ...		argument list for section
-	 * @return			enumerator over (char *key, char *value)
-	 */
-	enumerator_t* (*create_key_value_enumerator)(settings_t *this,
-												 char *section, ...);
-
-	/**
-	 * Add a fallback for the given section.
-	 *
-	 * Example: When the fallback 'section-two' is configured for
-	 * 'section-one.two' any failed lookup for a section or key in
-	 * 'section-one.two' will result in a lookup for the same section/key
-	 * in 'section-two'.
-	 *
-	 * @note Lookups are depth-first and currently strictly top-down.
-	 * For instance, if app.sec had lib1.sec as fallback and lib1 had lib2 as
-	 * fallback the keys/sections in lib2.sec would not be considered.  But if
-	 * app had lib3 as fallback the contents of lib3.sec would (as app is passed
-	 * during the initial lookup).  In the last example the order during
-	 * enumerations would be app.sec, lib1.sec, lib3.sec.
-	 *
-	 * @note Additional arguments will be applied to both section format
-	 * strings so they must be compatible.
-	 *
-	 * @param section	section for which a fallback is configured, printf style
-	 * @param fallback	fallback section, printf style
-	 * @param ...		argument list for section and fallback
-	 */
-	void (*add_fallback)(settings_t *this, const char *section,
-						 const char *fallback, ...);
-
-	/**
-	 * Load settings from the files matching the given pattern.
-	 *
-	 * If merge is TRUE, existing sections are extended, existing values
-	 * replaced, by those found in the loaded files. If it is FALSE, existing
-	 * sections are purged before reading the new config.
-	 *
-	 * @note If any of the files matching the pattern fails to load, no settings
-	 * are added at all. So, it's all or nothing.
-	 *
-	 * @param pattern	file pattern
-	 * @param merge		TRUE to merge config with existing values
-	 * @return			TRUE, if settings were loaded successfully
-	 */
-	bool (*load_files)(settings_t *this, char *pattern, bool merge);
-
-	/**
-	 * Load settings from the files matching the given pattern.
-	 *
-	 * If merge is TRUE, existing sections are extended, existing values
-	 * replaced, by those found in the loaded files. If it is FALSE, existing
-	 * sections are purged before reading the new config.
-	 *
-	 * All settings are loaded relative to the given section. The section is
-	 * created, if it does not yet exist.
-	 *
-	 * @note If any of the files matching the pattern fails to load, no settings
-	 * are added at all. So, it's all or nothing.
-	 *
-	 * @param pattern	file pattern
-	 * @param merge		TRUE to merge config with existing values
-	 * @param section	section name of parent section, printf style
-	 * @param ...		argument list for section
-	 * @return			TRUE, if settings were loaded successfully
-	 */
-	bool (*load_files_section)(settings_t *this, char *pattern, bool merge,
-							   char *section, ...);
-
-	/**
-	 * Destroy a settings instance.
-	 */
-	void (*destroy)(settings_t *this);
-};
-
-/**
- * Load settings from a file.
- *
- * @param file			file to read settings from, NULL for default
- * @return				settings object
- */
-settings_t *settings_create(char *file);
-
-#endif /** SETTINGS_H_ @}*/
diff --git a/src/libstrongswan/utils/test.c b/src/libstrongswan/utils/test.c
index 624ac4b..0b0a80f 100644
--- a/src/libstrongswan/utils/test.c
+++ b/src/libstrongswan/utils/test.c
@@ -20,13 +20,23 @@
 /**
  * A collection of testable functions
  */
-hashtable_t *testable_functions;
+static hashtable_t *functions = NULL;
+
+#ifndef WIN32
+bool test_runner_available __attribute__((weak));
+#endif
 
 /**
- * The function that actually initializes the hash table above.  Provided
- * by the test runner.
+ * Check if we have libtest linkage and need testable functions
  */
-void testable_functions_create() __attribute__((weak));
+static bool has_libtest_linkage()
+{
+#ifdef WIN32
+	return dlsym(RTLD_DEFAULT, "test_runner_available");
+#else
+	return test_runner_available;
+#endif
+}
 
 /*
  * Described in header.
@@ -35,33 +45,48 @@ void testable_function_register(char *name, void *fn)
 {
 	bool old = FALSE;
 
-	if (!testable_functions_create)
-	{	/* not linked to the test runner */
-		return;
-	}
-	else if (!fn && !testable_functions)
-	{	/* ignore as testable_functions has already been destroyed */
-		return;
-	}
-
 	if (lib && lib->leak_detective)
 	{
 		old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
 	}
-	if (!testable_functions)
-	{
-		testable_functions_create();
-	}
-	if (fn)
-	{
-		testable_functions->put(testable_functions, name, fn);
-	}
-	else
+
+	if (has_libtest_linkage())
 	{
-		testable_functions->remove(testable_functions, name);
+		if (!functions)
+		{
+			chunk_hash_seed();
+			functions = hashtable_create(hashtable_hash_str,
+										 hashtable_equals_str, 8);
+		}
+		if (fn)
+		{
+			functions->put(functions, name, fn);
+		}
+		else
+		{
+			functions->remove(functions, name);
+			if (functions->get_count(functions) == 0)
+			{
+				functions->destroy(functions);
+				functions = NULL;
+			}
+		}
 	}
+
 	if (lib && lib->leak_detective)
 	{
 		lib->leak_detective->set_state(lib->leak_detective, old);
 	}
 }
+
+/*
+ * Described in header.
+ */
+void* testable_function_get(char *name)
+{
+	if (functions)
+	{
+		return functions->get(functions, name);
+	}
+	return NULL;
+}
diff --git a/src/libstrongswan/utils/test.h b/src/libstrongswan/utils/test.h
index a1b2a2d..f9a8471 100644
--- a/src/libstrongswan/utils/test.h
+++ b/src/libstrongswan/utils/test.h
@@ -24,19 +24,20 @@
 #include "collections/hashtable.h"
 
 /**
- * Collection of testable functions.
+ * Register a (possibly static) function so that it can be called from tests.
  *
- * @note Is initialized only if libtest is loaded.
+ * @param name		name (namespace/function)
+ * @param fn		function to register (set to NULL to unregister)
  */
-extern hashtable_t *testable_functions;
+void testable_function_register(char *name, void *fn);
 
 /**
- * Register a (possibly static) function so that it can be called from tests.
+ * Find a previously registered testable function.
  *
  * @param name		name (namespace/function)
- * @param fn		function to register (set to NULL to unregister)
+ * @return			function, NULL if not found
  */
-void testable_function_register(char *name, void *fn);
+void* testable_function_get(char *name);
 
 /**
  * Macro to automatically register/unregister a function that can be called
@@ -82,10 +83,7 @@ static ret (*TEST_##ns##name)(__VA_ARGS__);
  */
 #define TEST_FUNCTION(ns, name, ...) \
 ({ \
-	if (testable_functions) \
-	{ \
-		TEST_##ns##name = testable_functions->get(testable_functions, #ns "/" #name); \
-	} \
+	TEST_##ns##name = testable_function_get( #ns "/" #name); \
 	if (!TEST_##ns##name) \
 	{ \
 		test_fail_msg(__FILE__, __LINE__, "function " #name " (" #ns ") not found"); \
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index fe80edb..02a7209 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -15,6 +15,13 @@
  */
 
 #define _GNU_SOURCE /* for memrchr */
+#ifdef WIN32
+/* for GetTickCount64, Windows 7 */
+# define _WIN32_WINNT 0x0601
+#endif
+
+#include "utils.h"
+
 #include <sys/stat.h>
 #include <string.h>
 #include <stdio.h>
@@ -24,13 +31,17 @@
 #include <limits.h>
 #include <dirent.h>
 #include <time.h>
-#include <pthread.h>
-
-#include "utils.h"
-
-#include "collections/enumerator.h"
-#include "utils/debug.h"
-#include "utils/chunk.h"
+#ifndef WIN32
+# include <signal.h>
+#endif
+
+#include <library.h>
+#include <utils/debug.h>
+#include <utils/chunk.h>
+#include <collections/enumerator.h>
+#include <threading/spinlock.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
 
 ENUM(status_names, SUCCESS, NEED_MORE,
 	"SUCCESS",
@@ -216,6 +227,84 @@ char* strreplace(const char *str, const char *search, const char *replace)
 	return res;
 }
 
+#ifdef WIN32
+
+/**
+ * Flag to indicate signaled wait_sigint()
+ */
+static bool sigint_signaled = FALSE;
+
+/**
+ * Condvar to wait in wait_sigint()
+ */
+static condvar_t *sigint_cond;
+
+/**
+ * Mutex to check signaling()
+ */
+static mutex_t *sigint_mutex;
+
+/**
+ * Control handler to catch ^C
+ */
+static BOOL WINAPI handler(DWORD dwCtrlType)
+{
+	switch (dwCtrlType)
+	{
+		case CTRL_C_EVENT:
+		case CTRL_BREAK_EVENT:
+		case CTRL_CLOSE_EVENT:
+			sigint_mutex->lock(sigint_mutex);
+			sigint_signaled = TRUE;
+			sigint_cond->signal(sigint_cond);
+			sigint_mutex->unlock(sigint_mutex);
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
+
+/**
+ * Windows variant
+ */
+void wait_sigint()
+{
+	SetConsoleCtrlHandler(handler, TRUE);
+
+	sigint_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+	sigint_cond = condvar_create(CONDVAR_TYPE_DEFAULT);
+
+	sigint_mutex->lock(sigint_mutex);
+	while (!sigint_signaled)
+	{
+		sigint_cond->wait(sigint_cond, sigint_mutex);
+	}
+	sigint_mutex->unlock(sigint_mutex);
+
+	sigint_mutex->destroy(sigint_mutex);
+	sigint_cond->destroy(sigint_cond);
+}
+
+#else /* !WIN32 */
+
+/**
+ * Unix variant
+ */
+void wait_sigint()
+{
+	sigset_t set;
+	int sig;
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGINT);
+	sigaddset(&set, SIGTERM);
+
+	sigprocmask(SIG_BLOCK, &set, NULL);
+	sigwait(&set, &sig);
+}
+
+#endif
+
 /**
  * Described in header.
  */
@@ -223,21 +312,30 @@ char* path_dirname(const char *path)
 {
 	char *pos;
 
-	pos = path ? strrchr(path, '/') : NULL;
+	pos = path ? strrchr(path, DIRECTORY_SEPARATOR[0]) : NULL;
 
 	if (pos && !pos[1])
 	{	/* if path ends with slashes we have to look beyond them */
-		while (pos > path && *pos == '/')
+		while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
 		{	/* skip trailing slashes */
 			pos--;
 		}
-		pos = memrchr(path, '/', pos - path + 1);
+		pos = memrchr(path, DIRECTORY_SEPARATOR[0], pos - path + 1);
 	}
 	if (!pos)
 	{
+#ifdef WIN32
+		if (path && strlen(path))
+		{
+			if ((isalpha(path[0]) && path[1] == ':'))
+			{	/* if just a drive letter given, return that as dirname */
+				return chunk_clone(chunk_from_chars(path[0], ':', 0)).ptr;
+			}
+		}
+#endif
 		return strdup(".");
 	}
-	while (pos > path && *pos == '/')
+	while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
 	{	/* skip superfluous slashes */
 		pos--;
 	}
@@ -255,19 +353,19 @@ char* path_basename(const char *path)
 	{
 		return strdup(".");
 	}
-	pos = strrchr(path, '/');
+	pos = strrchr(path, DIRECTORY_SEPARATOR[0]);
 	if (pos && !pos[1])
 	{	/* if path ends with slashes we have to look beyond them */
-		while (pos > path && *pos == '/')
+		while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
 		{	/* skip trailing slashes */
 			pos--;
 		}
-		if (pos == path && *pos == '/')
+		if (pos == path && *pos == DIRECTORY_SEPARATOR[0])
 		{	/* contains only slashes */
-			return strdup("/");
+			return strdup(DIRECTORY_SEPARATOR);
 		}
 		trail = pos + 1;
-		pos = memrchr(path, '/', trail - path);
+		pos = memrchr(path, DIRECTORY_SEPARATOR[0], trail - path);
 	}
 	pos = pos ? pos + 1 : (char*)path;
 	return trail ? strndup(pos, trail - pos) : strdup(pos);
@@ -276,6 +374,33 @@ char* path_basename(const char *path)
 /**
  * Described in header.
  */
+bool path_absolute(const char *path)
+{
+	if (!path)
+	{
+		return FALSE;
+	}
+#ifdef WIN32
+	if (strpfx(path, "\\\\"))
+	{	/* UNC */
+		return TRUE;
+	}
+	if (strlen(path) && isalpha(path[0]) && path[1] == ':')
+	{	/* drive letter */
+		return TRUE;
+	}
+#else /* !WIN32 */
+	if (path[0] == DIRECTORY_SEPARATOR[0])
+	{
+		return TRUE;
+	}
+#endif
+	return FALSE;
+}
+
+/**
+ * Described in header.
+ */
 bool mkdir_p(const char *path, mode_t mode)
 {
 	int len;
@@ -307,7 +432,11 @@ bool mkdir_p(const char *path, mode_t mode)
 		*pos = '\0';
 		if (access(full, F_OK) < 0)
 		{
+#ifdef WIN32
+			if (_mkdir(full) < 0)
+#else
 			if (mkdir(full, mode) < 0)
+#endif
 			{
 				DBG1(DBG_LIB, "failed to create directory %s", full);
 				return FALSE;
@@ -359,6 +488,9 @@ char* tty_escape_get(int fd, tty_escape_t escape)
 		case TTY_BOLD:
 		case TTY_UNDERLINE:
 		case TTY_BLINKING:
+#ifdef WIN32
+			return "";
+#endif
 		case TTY_FG_BLACK:
 		case TTY_FG_RED:
 		case TTY_FG_GREEN:
@@ -378,7 +510,7 @@ char* tty_escape_get(int fd, tty_escape_t escape)
 		case TTY_BG_WHITE:
 		case TTY_BG_DEF:
 			return enum_to_name(tty_color_names, escape);
-		/* warn if a excape code is missing */
+		/* warn if a escape code is missing */
 	}
 	return "";
 }
@@ -414,7 +546,11 @@ void closefrom(int lowfd)
 	}
 
 	/* ...fall back to closing all fds otherwise */
+#ifdef WIN32
+	maxfd = _getmaxstdio();
+#else
 	maxfd = (int)sysconf(_SC_OPEN_MAX);
+#endif
 	if (maxfd < 0)
 	{
 		maxfd = 256;
@@ -431,6 +567,19 @@ void closefrom(int lowfd)
  */
 time_t time_monotonic(timeval_t *tv)
 {
+#ifdef WIN32
+	ULONGLONG ms;
+	time_t s;
+
+	ms = GetTickCount64();
+	s = ms / 1000;
+	if (tv)
+	{
+		tv->tv_sec = s;
+		tv->tv_usec = (ms - (s * 1000)) * 1000;
+	}
+	return s;
+#else /* !WIN32 */
 #if defined(HAVE_CLOCK_GETTIME) && \
 	(defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
 	 defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
@@ -462,6 +611,7 @@ time_t time_monotonic(timeval_t *tv)
 		return -1;
 	}
 	return tv->tv_sec;
+#endif /* !WIN32 */
 }
 
 /**
@@ -511,12 +661,12 @@ void nop()
 {
 }
 
-#ifndef HAVE_GCC_ATOMIC_OPERATIONS
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
 
 /**
- * We use a single mutex for all refcount variables.
+ * Spinlock for ref_get/put
  */
-static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
+static spinlock_t *ref_lock;
 
 /**
  * Increase refcount
@@ -525,9 +675,9 @@ refcount_t ref_get(refcount_t *ref)
 {
 	refcount_t current;
 
-	pthread_mutex_lock(&ref_mutex);
+	ref_lock->lock(ref_lock);
 	current = ++(*ref);
-	pthread_mutex_unlock(&ref_mutex);
+	ref_lock->unlock(ref_lock);
 
 	return current;
 }
@@ -539,16 +689,30 @@ bool ref_put(refcount_t *ref)
 {
 	bool more_refs;
 
-	pthread_mutex_lock(&ref_mutex);
+	ref_lock->lock(ref_lock);
 	more_refs = --(*ref) > 0;
-	pthread_mutex_unlock(&ref_mutex);
+	ref_lock->unlock(ref_lock);
 	return !more_refs;
 }
 
 /**
- * Single mutex for all compare and swap operations.
+ * Current refcount
+ */
+refcount_t ref_cur(refcount_t *ref)
+{
+	refcount_t current;
+
+	ref_lock->lock(ref_lock);
+	current = *ref;
+	ref_lock->unlock(ref_lock);
+
+	return current;
+}
+
+/**
+ * Spinlock for all compare and swap operations.
  */
-static pthread_mutex_t cas_mutex = PTHREAD_MUTEX_INITIALIZER;
+static spinlock_t *cas_lock;
 
 /**
  * Compare and swap if equal to old value
@@ -557,16 +721,16 @@ static pthread_mutex_t cas_mutex = PTHREAD_MUTEX_INITIALIZER;
 bool cas_##name(type *ptr, type oldval, type newval) \
 { \
 	bool swapped; \
-	pthread_mutex_lock(&cas_mutex); \
+	cas_lock->lock(cas_lock); \
 	if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
-	pthread_mutex_unlock(&cas_mutex); \
+	cas_lock->unlock(cas_lock); \
 	return swapped; \
 }
 
 _cas_impl(bool, bool)
 _cas_impl(ptr, void*)
 
-#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+#endif /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
 
 
 #ifdef HAVE_FMEMOPEN_FALLBACK
@@ -614,6 +778,40 @@ FILE *fmemopen(void *buf, size_t size, const char *mode)
 #endif /* FMEMOPEN fallback*/
 
 /**
+ * See header
+ */
+void utils_init()
+{
+#ifdef WIN32
+	windows_init();
+#endif
+
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+	ref_lock = spinlock_create();
+	cas_lock = spinlock_create();
+#endif
+
+	strerror_init();
+}
+
+/**
+ * See header
+ */
+void utils_deinit()
+{
+#ifdef WIN32
+	windows_deinit();
+#endif
+
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+	ref_lock->destroy(ref_lock);
+	cas_lock->destroy(cas_lock);
+#endif
+
+	strerror_deinit();
+}
+
+/**
  * Described in header.
  */
 int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
@@ -625,20 +823,23 @@ int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
 	};
 	time_t *time = *((time_t**)(args[0]));
 	bool utc = *((int*)(args[1]));
-	struct tm t;
+	struct tm t, *ret = NULL;
 
-	if (*time == UNDEFINED_TIME)
+	if (*time != UNDEFINED_TIME)
 	{
-		return print_in_hook(data, "--- -- --:--:--%s----",
-							 utc ? " UTC " : " ");
-	}
-	if (utc)
-	{
-		gmtime_r(time, &t);
+		if (utc)
+		{
+			ret = gmtime_r(time, &t);
+		}
+		else
+		{
+			ret = localtime_r(time, &t);
+		}
 	}
-	else
+	if (ret == NULL)
 	{
-		localtime_r(time, &t);
+		return print_in_hook(data, "--- -- --:--:--%s----",
+							 utc ? " UTC " : " ");
 	}
 	return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
 						 months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
index a55e7d8..1b822dd 100644
--- a/src/libstrongswan/utils/utils.h
+++ b/src/libstrongswan/utils/utils.h
@@ -26,11 +26,18 @@
 #include <stdlib.h>
 #include <stddef.h>
 #include <sys/time.h>
-#include <arpa/inet.h>
 #include <string.h>
 
-#include "enum.h"
-#include "utils/strerror.h"
+#ifdef WIN32
+# include "windows.h"
+#else
+# define _GNU_SOURCE
+# include <arpa/inet.h>
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sched.h>
+#endif
 
 /**
  * strongSwan program return codes
@@ -73,6 +80,28 @@
 # define TRUE  true
 #endif /* TRUE */
 
+#include "enum.h"
+#include "utils/strerror.h"
+
+/**
+ * Directory separator character in paths on this platform
+ */
+#ifdef WIN32
+# define DIRECTORY_SEPARATOR "\\"
+#else
+# define DIRECTORY_SEPARATOR "/"
+#endif
+
+/**
+ * Initialize utility functions
+ */
+void utils_init();
+
+/**
+ * Deinitialize utility functions
+ */
+void utils_deinit();
+
 /**
  * Helper function that compares two strings for equality
  */
@@ -138,6 +167,48 @@ static inline bool memeq(const void *x, const void *y, size_t len)
 }
 
 /**
+ * Calling memcpy() with NULL pointers, even with n == 0, results in undefined
+ * behavior according to the C standard.  This version is guaranteed to not
+ * access the pointers if n is 0.
+ */
+static inline void *memcpy_noop(void *dst, const void *src, size_t n)
+{
+	return n ? memcpy(dst, src, n) : dst;
+}
+#ifdef memcpy
+# undef memcpy
+#endif
+#define memcpy(d,s,n) memcpy_noop(d,s,n)
+
+/**
+ * Calling memmove() with NULL pointers, even with n == 0, results in undefined
+ * behavior according to the C standard.  This version is guaranteed to not
+ * access the pointers if n is 0.
+ */
+static inline void *memmove_noop(void *dst, const void *src, size_t n)
+{
+	return n ? memmove(dst, src, n) : dst;
+}
+#ifdef memmove
+# undef memmove
+#endif
+#define memmove(d,s,n) memmove_noop(d,s,n)
+
+/**
+ * Calling memset() with a NULL pointer, even with n == 0, results in undefined
+ * behavior according to the C standard.  This version is guaranteed to not
+ * access the pointer if n is 0.
+ */
+static inline void *memset_noop(void *s, int c, size_t n)
+{
+	return n ? memset(s, c, n) : s;
+}
+#ifdef memset
+# undef memset
+#endif
+#define memset(s,c,n) memset_noop(s,c,n)
+
+/**
  * Macro gives back larger of two values.
  */
 #define max(x,y) ({ \
@@ -145,7 +216,6 @@ static inline bool memeq(const void *x, const void *y, size_t len)
 	typeof(y) _y = (y); \
 	_x > _y ? _x : _y; })
 
-
 /**
  * Macro gives back smaller of two values.
  */
@@ -204,6 +274,45 @@ static inline bool memeq(const void *x, const void *y, size_t len)
 	static ret name(this, ##__VA_ARGS__)
 
 /**
+ * Callback declaration/definition macro, allowing casted first parameter.
+ *
+ * This is very similar to METHOD, but instead of casting the first parameter
+ * to a public interface, it uses a void*. This allows type safe definition
+ * of a callback function, while using the real type for the first parameter.
+ */
+#define CALLBACK(name, ret, param1, ...) \
+	static ret _cb_##name(union {void *_generic; param1;} \
+	__attribute__((transparent_union)), ##__VA_ARGS__); \
+	static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \
+	static ret _cb_##name(param1, ##__VA_ARGS__)
+
+/**
+ * This macro allows counting the number of arguments passed to a macro.
+ * Combined with the VA_ARGS_DISPATCH() macro this can be used to implement
+ * macro overloading based on the number of arguments.
+ * 0 to 10 arguments are currently supported.
+ */
+#define VA_ARGS_NUM(...) _VA_ARGS_NUM(0,##__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0)
+#define _VA_ARGS_NUM(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,NUM,...) NUM
+
+/**
+ * This macro can be used to dispatch a macro call based on the number of given
+ * arguments, for instance:
+ *
+ * @code
+ * #define MY_MACRO(...) VA_ARGS_DISPATCH(MY_MACRO, __VA_ARGS__)(__VA_ARGS__)
+ * #define MY_MACRO1(arg) one_arg(arg)
+ * #define MY_MACRO2(arg1,arg2) two_args(arg1,arg2)
+ * @endcode
+ *
+ * MY_MACRO() can now be called with either one or two arguments, which will
+ * resolve to one_arg(arg) or two_args(arg1,arg2), respectively.
+ */
+#define VA_ARGS_DISPATCH(func, ...) _VA_ARGS_DISPATCH(func, VA_ARGS_NUM(__VA_ARGS__))
+#define _VA_ARGS_DISPATCH(func, num) __VA_ARGS_DISPATCH(func, num)
+#define __VA_ARGS_DISPATCH(func, num) func ## num
+
+/**
  * Architecture independent bitfield definition helpers (at least with GCC).
  *
  * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
@@ -260,7 +369,7 @@ static inline bool memeq(const void *x, const void *y, size_t len)
  * TODO: since the uintXX_t types are defined by the C99 standard we should
  * probably use those anyway
  */
-#ifdef __sun
+#if defined __sun || defined WIN32
         #include <stdint.h>
         typedef uint8_t         u_int8_t;
         typedef uint16_t        u_int16_t;
@@ -501,6 +610,11 @@ char *translate(char *str, const char *from, const char *to);
 char *strreplace(const char *str, const char *search, const char *replace);
 
 /**
+ * Portable function to wait for SIGINT/SIGTERM (or equivalent).
+ */
+void wait_sigint();
+
+/**
  * Like dirname(3) returns the directory part of the given null-terminated
  * pathname, up to but not including the final '/' (or '.' if no '/' is found).
  * Trailing '/' are not counted as part of the pathname.
@@ -527,6 +641,14 @@ char *path_dirname(const char *path);
 char *path_basename(const char *path);
 
 /**
+ * Check if a given path is absolute.
+ *
+ * @param path		path to check
+ * @return			TRUE if absolute, FALSE if relative
+ */
+bool path_absolute(const char *path);
+
+/**
  * Creates a directory and all required parent directories.
  *
  * @param path		path to the new directory
@@ -748,22 +870,49 @@ static inline size_t round_down(size_t size, size_t alignment)
  */
 typedef u_int refcount_t;
 
+/* use __atomic* built-ins with GCC 4.7 and newer */
+#ifdef __GNUC__
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+#  define HAVE_GCC_ATOMIC_OPERATIONS
+# endif
+#endif
+
 #ifdef HAVE_GCC_ATOMIC_OPERATIONS
 
+#define ref_get(ref) __atomic_add_fetch(ref, 1, __ATOMIC_RELAXED)
+/* The relaxed memory model works fine for increments as these (usually) don't
+ * change the state of refcounted objects.  But here we have to ensure that we
+ * free the right stuff if ref counted objects are mutable.  So we have to sync
+ * with other threads that call ref_put().  It would be sufficient to use
+ * __ATOMIC_RELEASE here and then call __atomic_thread_fence() with
+ * __ATOMIC_ACQUIRE if we reach 0, but since we don't have control over the use
+ * of ref_put() we have to make sure. */
+#define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL))
+#define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED)
+
+#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \
+			__atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \
+										__ATOMIC_SEQ_CST, __ATOMIC_RELAXED); })
+#define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
+#define cas_ptr(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
+
+#elif defined(HAVE_GCC_SYNC_OPERATIONS)
+
 #define ref_get(ref) __sync_add_and_fetch(ref, 1)
 #define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
+#define ref_cur(ref) __sync_fetch_and_add(ref, 0)
 
 #define cas_bool(ptr, oldval, newval) \
 					(__sync_bool_compare_and_swap(ptr, oldval, newval))
 #define cas_ptr(ptr, oldval, newval) \
 					(__sync_bool_compare_and_swap(ptr, oldval, newval))
 
-#else /* !HAVE_GCC_ATOMIC_OPERATIONS */
+#else /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
 
 /**
  * Get a new reference.
  *
- * Increments the reference counter atomic.
+ * Increments the reference counter atomically.
  *
  * @param ref	pointer to ref counter
  * @return		new value of ref
@@ -773,7 +922,7 @@ refcount_t ref_get(refcount_t *ref);
 /**
  * Put back a unused reference.
  *
- * Decrements the reference counter atomic and
+ * Decrements the reference counter atomically and
  * says if more references available.
  *
  * @param ref	pointer to ref counter
@@ -782,6 +931,14 @@ refcount_t ref_get(refcount_t *ref);
 bool ref_put(refcount_t *ref);
 
 /**
+ * Get the current value of the reference counter.
+ *
+ * @param ref	pointer to ref counter
+ * @return		current value of ref
+ */
+refcount_t ref_cur(refcount_t *ref);
+
+/**
  * Atomically replace value of ptr with newval if it currently equals oldval.
  *
  * @param ptr		pointer to variable
diff --git a/src/libstrongswan/utils/utils/strerror.c b/src/libstrongswan/utils/utils/strerror.c
index 95e463f..d35bbec 100644
--- a/src/libstrongswan/utils/utils/strerror.c
+++ b/src/libstrongswan/utils/utils/strerror.c
@@ -15,7 +15,10 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <pthread.h>
+
+#include <library.h>
+#include <threading/thread_value.h>
+#include <threading/spinlock.h>
 
 #include "strerror.h"
 
@@ -25,22 +28,16 @@
 #define STRERROR_BUF_LEN 256
 
 /**
- * Key to store thread-specific error buffer
- */
-static pthread_key_t strerror_buf_key;
-
-/**
- * Only initialize the key above once
+ * Thread specific strerror buffer, as char*
  */
-static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
+static thread_value_t *strerror_buf;
 
+#ifndef HAVE_STRERROR_R
 /**
- * Create the key used for the thread-specific error buffer
+ * Lock to access strerror() safely
  */
-static void create_strerror_buf_key()
-{
-	pthread_key_create(&strerror_buf_key, free);
-}
+static spinlock_t *strerror_lock;
+#endif /* HAVE_STRERROR_R */
 
 /**
  * Retrieve the error buffer assigned to the current thread (or create it)
@@ -48,50 +45,103 @@ static void create_strerror_buf_key()
 static inline char *get_strerror_buf()
 {
 	char *buf;
+	bool old = FALSE;
 
-	pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
-	buf = pthread_getspecific(strerror_buf_key);
+	if (!strerror_buf)
+	{
+		return NULL;
+	}
+
+	buf = strerror_buf->get(strerror_buf);
 	if (!buf)
 	{
+		if (lib->leak_detective)
+		{
+			old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
+		}
 		buf = malloc(STRERROR_BUF_LEN);
-		pthread_setspecific(strerror_buf_key, buf);
+		strerror_buf->set(strerror_buf, buf);
+		if (lib->leak_detective)
+		{
+			lib->leak_detective->set_state(lib->leak_detective, old);
+		}
 	}
 	return buf;
 }
 
-#ifdef HAVE_STRERROR_R
+/**
+ * Use real strerror() below
+ */
+#undef strerror
+
 /*
  * Described in header.
  */
 const char *strerror_safe(int errnum)
 {
-	char *buf = get_strerror_buf(), *msg;
+	char *buf, *msg;
 
-#ifdef STRERROR_R_CHAR_P
+	buf = get_strerror_buf();
+	if (!buf)
+	{
+		/* library not initialized? fallback */
+		return strerror(errnum);
+	}
+#ifdef HAVE_STRERROR_R
+# ifdef STRERROR_R_CHAR_P
 	/* char* version which may or may not return the original buffer */
 	msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
-#else
+# else
 	/* int version returns 0 on success */
 	msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
-#endif
+# endif
+#else /* HAVE_STRERROR_R */
+	/* use a lock to ensure calling strerror(3) is thread-safe */
+	strerror_lock->lock(strerror_lock);
+	msg = strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
+	strerror_lock->unlock(strerror_lock);
+	buf[STRERROR_BUF_LEN - 1] = '\0';
+#endif /* HAVE_STRERROR_R */
 	return msg;
 }
-#else /* HAVE_STRERROR_R */
-/* we actually wan't to call strerror(3) below */
-#undef strerror
-/*
- * Described in header.
+
+/**
+ * free() with disabled leak detective
  */
-const char *strerror_safe(int errnum)
+static void free_no_ld(void *buf)
 {
-	static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-	char *buf = get_strerror_buf();
+	bool old = FALSE;
 
-	/* use a mutex to ensure calling strerror(3) is thread-safe */
-	pthread_mutex_lock(&mutex);
-	strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
-	pthread_mutex_unlock(&mutex);
-	buf[STRERROR_BUF_LEN - 1] = '\0';
-	return buf;
+	if (lib->leak_detective)
+	{
+		old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
+	}
+	free(buf);
+	if (lib->leak_detective)
+	{
+		lib->leak_detective->set_state(lib->leak_detective, old);
+	}
+}
+
+/**
+ * See header
+ */
+void strerror_init()
+{
+	strerror_buf = thread_value_create(free_no_ld);
+#ifndef HAVE_STRERROR_R
+	strerror_lock = spinlock_create();
+#endif
+}
+
+/**
+ * See header
+ */
+void strerror_deinit()
+{
+	strerror_buf->destroy(strerror_buf);
+	strerror_buf = NULL;
+#ifndef HAVE_STRERROR_R
+	strerror_lock->destroy(strerror_lock);
+#endif
 }
-#endif /* HAVE_STRERROR_R */
diff --git a/src/libstrongswan/utils/utils/strerror.h b/src/libstrongswan/utils/utils/strerror.h
index 2cb76f1..e1b0638 100644
--- a/src/libstrongswan/utils/utils/strerror.h
+++ b/src/libstrongswan/utils/utils/strerror.h
@@ -33,6 +33,16 @@
 const char *strerror_safe(int errnum);
 
 /**
+ * Initialize strerror_safe()
+ */
+void strerror_init();
+
+/**
+ * Deinitialize strerror_safe()
+ */
+void strerror_deinit();
+
+/**
  * Replace usages of strerror(3) with thread-safe variant.
  */
 #define strerror(errnum) strerror_safe(errnum)
diff --git a/src/libstrongswan/utils/windows.c b/src/libstrongswan/utils/windows.c
new file mode 100644
index 0000000..8820287
--- /dev/null
+++ b/src/libstrongswan/utils/windows.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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 "utils.h"
+
+#include <errno.h>
+
+/**
+ * See header
+ */
+void windows_init()
+{
+	WSADATA wsad;
+
+	/* initialize winsock2 */
+	WSAStartup(MAKEWORD(2, 2), &wsad);
+}
+
+/**
+ * See header
+ */
+void windows_deinit()
+{
+	WSACleanup();
+}
+
+/**
+ * See header
+ */
+int usleep(useconds_t usec)
+{
+	if (usec > 0 && usec < 1000)
+	{	/* do not Sleep(0) for small values */
+		usec = 1000;
+	}
+	SleepEx(usec / 1000, TRUE);
+	return 0;
+}
+
+/**
+ * See header.
+ */
+char* strndup(const char *s, size_t n)
+{
+	char *dst;
+
+	n = min(strnlen(s, n), n);
+	dst = malloc(n + 1);
+	memcpy(dst, s, n);
+	dst[n] = '\0';
+
+	return dst;
+}
+
+/*
+ * See header.
+ */
+void *dlopen(const char *filename, int flag)
+{
+	return LoadLibrary(filename);
+}
+
+/**
+ * Load a symbol from known default libs (monolithic build)
+ */
+static void* dlsym_default(const char *name)
+{
+	const char *dlls[] = {
+		"libstrongswan-0.dll",
+		"libhydra-0.dll",
+		"libcharon-0.dll",
+		"libtnccs-0.dll",
+		NULL /* .exe */
+	};
+	HANDLE handle;
+	void *sym = NULL;
+	int i;
+
+	for (i = 0; i < countof(dlls); i++)
+	{
+		handle = GetModuleHandle(dlls[i]);
+		if (handle)
+		{
+			sym = GetProcAddress(handle, name);
+			if (sym)
+			{
+				break;
+			}
+		}
+	}
+	return sym;
+}
+
+/**
+ * Emulate RTLD_NEXT for some known symbols
+ */
+static void* dlsym_next(const char *name)
+{
+	struct {
+		const char *dll;
+		const char *syms[4];
+	} dlls[] = {
+		/* for leak detective */
+		{ "msvcrt",
+			{ "malloc", "calloc", "realloc", "free" }
+		},
+	};
+	HANDLE handle = NULL;
+	int i, j;
+
+	for (i = 0; i < countof(dlls); i++)
+	{
+		for (j = 0; j < countof(dlls[0].syms); j++)
+		{
+			if (dlls[i].syms[j] && streq(dlls[i].syms[j], name))
+			{
+				handle = GetModuleHandle(dlls[i].dll);
+				break;
+			}
+		}
+	}
+	if (handle)
+	{
+		return GetProcAddress(handle, name);
+	}
+	return handle;
+}
+
+/**
+ * See header.
+ */
+void* dlsym(void *handle, const char *symbol)
+{
+	if (handle == RTLD_DEFAULT)
+	{
+		return dlsym_default(symbol);
+	}
+	if (handle == RTLD_NEXT)
+	{
+		return dlsym_next(symbol);
+	}
+	return GetProcAddress((HMODULE)handle, symbol);
+}
+
+/**
+ * See header.
+ */
+char* dlerror(void)
+{
+	static char buf[128];
+	char *pos;
+	DWORD err;
+
+	err = GetLastError();
+	if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+					  NULL, err, 0, buf, sizeof(buf), NULL) > 0)
+	{
+		pos = strchr(buf, '\n');
+		if (pos)
+		{
+			*pos = '\0';
+		}
+	}
+	else
+	{
+		snprintf(buf, sizeof(buf), "(%u)", err);
+	}
+	return buf;
+}
+
+/**
+ * See header.
+ */
+int dlclose(void *handle)
+{
+	return FreeLibrary((HMODULE)handle);
+}
+
+/**
+ * See header
+ */
+int socketpair(int domain, int type, int protocol, int sv[2])
+{
+	struct sockaddr_in addr = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+	};
+	socklen_t len = sizeof(addr);
+	int s, c, sc;
+	BOOL on;
+
+	/* We don't check domain for AF_INET, as we use it as replacement for
+	 * AF_UNIX. */
+	if (type != SOCK_STREAM)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	if (protocol != 0 && protocol != IPPROTO_TCP)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (s == -1)
+	{
+		return -1;
+	}
+	c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (c == -1)
+	{
+		closesocket(s);
+		return -1;
+	}
+	if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == 0 &&
+		getsockname(s,(struct sockaddr*)&addr, &len) == 0 &&
+		listen(s, 0) == 0 &&
+		connect(c, (struct sockaddr*)&addr, sizeof(addr)) == 0)
+	{
+		sc = accept(s, NULL, NULL);
+		if (sc >= 0)
+		{
+			closesocket(s);
+			s = sc;
+			if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
+						   (void*)&on, sizeof(on)) == 0 &&
+				setsockopt(c, IPPROTO_TCP, TCP_NODELAY,
+						   (void*)&on, sizeof(on)) == 0)
+			{
+				sv[0] = s;
+				sv[1] = c;
+				return 0;
+			}
+		}
+	}
+	closesocket(s);
+	closesocket(c);
+	return -1;
+}
+
+/**
+ * See header
+ */
+char* getpass(const char *prompt)
+{
+	static char buf[64] = "";
+	char *pos;
+	HANDLE in, out;
+	DWORD mode, written = 0, total, done;
+
+	out = GetStdHandle(STD_OUTPUT_HANDLE);
+	in = GetStdHandle(STD_INPUT_HANDLE);
+
+	if (out == INVALID_HANDLE_VALUE || in == INVALID_HANDLE_VALUE ||
+		!GetConsoleMode(out, &mode) || !GetConsoleMode(in, &mode))
+	{
+		return NULL;
+	}
+
+	total = strlen(prompt);
+	while (written < total)
+	{
+		if (!WriteConsole(out, prompt + written, total - written, &done, NULL))
+		{
+			return NULL;
+		}
+		written += done;
+	}
+
+	if (!SetConsoleMode(in, mode & ~ENABLE_ECHO_INPUT))
+	{
+		return NULL;
+	}
+
+	while (TRUE)
+	{
+		if (!ReadConsole(in, buf, sizeof(buf), &done, NULL))
+		{
+			SetConsoleMode(in, mode);
+			return NULL;
+		}
+		buf[sizeof(buf)-1] = '\0';
+
+		if (done)
+		{
+			pos = strchr(buf, '\r');
+			if (pos)
+			{
+				*pos = '\0';
+			}
+			break;
+		}
+	}
+	SetConsoleMode(in, mode);
+
+	/* append a newline, as we have no echo during input */
+	WriteConsole(out, "\r\n", 2, &done, NULL);
+
+	return buf;
+}
+
+/**
+ * See header.
+ */
+#undef strerror_s
+int strerror_s_extended(char *buf, size_t buflen, int errnum)
+{
+	const char *errstr [] = {
+		/* EADDRINUSE */		"Address in use",
+		/* EADDRNOTAVAIL */		"Address not available",
+		/* EAFNOSUPPORT */		"Address family not supported",
+		/* EALREADY */			"Connection already in progress",
+		/* EBADMSG */			"Bad message",
+		/* ECANCELED */			"Operation canceled",
+		/* ECONNABORTED */		"Connection aborted",
+		/* ECONNREFUSED */		"Connection refused",
+		/* ECONNRESET */		"Connection reset",
+		/* EDESTADDRREQ */		"Destination address required",
+		/* EHOSTUNREACH */		"Host is unreachable",
+		/* EIDRM */				"Identifier removed",
+		/* EINPROGRESS */		"Operation in progress",
+		/* EISCONN */			"Socket is connected",
+		/* ELOOP */				"Too many levels of symbolic links",
+		/* EMSGSIZE */			"Message too large",
+		/* ENETDOWN */			"Network is down",
+		/* ENETRESET */			"Connection aborted by network",
+		/* ENETUNREACH */		"Network unreachable",
+		/* ENOBUFS */			"No buffer space available",
+		/* ENODATA */			"No message is available",
+		/* ENOLINK */			"No link",
+		/* ENOMSG */			"No message of the desired type",
+		/* ENOPROTOOPT */		"Protocol not available",
+		/* ENOSR */				"No stream resources",
+		/* ENOSTR */			"Not a stream",
+		/* ENOTCONN */			"The socket is not connected",
+		/* ENOTRECOVERABLE */	"State not recoverable",
+		/* ENOTSOCK */			"Not a socket",
+		/* ENOTSUP */			"Not supported",
+		/* EOPNOTSUPP */		"Operation not supported on socket",
+		/* EOTHER */			"Other error",
+		/* EOVERFLOW */			"Value too large to be stored in data type",
+		/* EOWNERDEAD */		"Previous owner died",
+		/* EPROTO */			"Protocol error",
+		/* EPROTONOSUPPORT */	"Protocol not supported",
+		/* EPROTOTYPE */		"Protocol wrong type for socket",
+		/* ETIME */				"Timeout",
+		/* ETIMEDOUT */			"Connection timed out",
+		/* ETXTBSY */			"Text file busy",
+		/* EWOULDBLOCK */		"Operation would block",
+	};
+	int offset = EADDRINUSE;
+
+	if (errnum < offset || errnum >= offset + countof(errstr))
+	{
+		return strerror_s(buf, buflen, errnum);
+	}
+	strncpy(buf, errstr[errnum - offset], buflen);
+	buf[buflen - 1] = '\0';
+	return 0;
+}
+
+/**
+ * Set errno for a function setting WSA error on failure
+ */
+static int wserr(int retval)
+{
+	if (retval < 0)
+	{
+		static const struct {
+			DWORD wsa;
+			int err;
+		} map[] = {
+			{ WSANOTINITIALISED,			EBADF						},
+			{ WSAENETDOWN,					ENETDOWN					},
+			{ WSAENETRESET,					ENETRESET					},
+			{ WSAECONNABORTED,				ECONNABORTED				},
+			{ WSAESHUTDOWN,					ECONNABORTED				},
+			{ WSAEACCES,					EACCES						},
+			{ WSAEINTR,						EINTR						},
+			{ WSAEINPROGRESS,				EINPROGRESS					},
+			{ WSAEFAULT,					EFAULT						},
+			{ WSAENOBUFS,					ENOBUFS						},
+			{ WSAENOTSOCK,					ENOTSOCK					},
+			{ WSAEOPNOTSUPP,				EOPNOTSUPP					},
+			{ WSAEWOULDBLOCK,				EWOULDBLOCK					},
+			{ WSAEMSGSIZE,					EMSGSIZE					},
+			{ WSAEINVAL,					EINVAL						},
+			{ WSAENOTCONN,					ENOTCONN					},
+			{ WSAEHOSTUNREACH,				EHOSTUNREACH				},
+			{ WSAENETUNREACH,				ENETUNREACH					},
+			{ WSAECONNABORTED,				ECONNABORTED				},
+			{ WSAECONNRESET,				ECONNRESET					},
+			{ WSAETIMEDOUT,					ETIMEDOUT					},
+			{ WSAEMFILE,					EMFILE						},
+			{ WSAEALREADY,					EALREADY					},
+			{ WSAEDESTADDRREQ,				EDESTADDRREQ				},
+			{ WSAEISCONN,					EISCONN						},
+			{ WSAEOPNOTSUPP,				EOPNOTSUPP					},
+			{ WSAEPROTOTYPE,				EPROTOTYPE					},
+			{ WSAENOPROTOOPT,				ENOPROTOOPT					},
+			{ WSAEPROTONOSUPPORT,			EPROTONOSUPPORT				},
+			{ WSAEPFNOSUPPORT,				EPROTONOSUPPORT				},
+			{ WSAEAFNOSUPPORT,				EAFNOSUPPORT				},
+			{ WSAEADDRNOTAVAIL,				EADDRNOTAVAIL				},
+			{ WSAEADDRINUSE,				EADDRINUSE					},
+			{ WSAETIMEDOUT,					ETIMEDOUT					},
+			{ WSAECONNREFUSED,				ECONNREFUSED				},
+			{ WSAELOOP,						ELOOP						},
+			{ WSAENAMETOOLONG,				ENAMETOOLONG				},
+			{ WSAENOTEMPTY,					ENOTEMPTY					},
+			{ WSAEPROTOTYPE,				EPROTOTYPE					},
+			{ WSAVERNOTSUPPORTED,			ENOTSUP						},
+		};
+		DWORD wsa, i;
+
+		wsa = WSAGetLastError();
+		for (i = 0; i < countof(map); i++)
+		{
+			if (map[i].wsa == wsa)
+			{
+				errno = map[i].err;
+				return retval;
+			}
+		}
+		errno = ENOENT;
+		return retval;
+	}
+	errno = 0;
+	return retval;
+}
+
+/**
+ * Check and clear the dontwait flag
+ */
+static bool check_dontwait(int *flags)
+{
+	if (*flags & MSG_DONTWAIT)
+	{
+		*flags &= ~MSG_DONTWAIT;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * See header
+ */
+#undef shutdown
+int windows_shutdown(int sockfd, int how)
+{
+	return wserr(shutdown(sockfd, how));
+}
+
+/**
+ * See header
+ */
+#undef accept
+int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+	return wserr(accept(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef bind
+int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+	return wserr(bind(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef connect
+int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+	return wserr(connect(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef getsockname
+int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+	return wserr(getsockname(sockfd, addr, addrlen));
+}
+
+/**
+ * See header
+ */
+#undef getsockopt
+int windows_getsockopt(int sockfd, int level, int optname,
+					   void *optval, socklen_t *optlen)
+{
+	return wserr(getsockopt(sockfd, level, optname, optval, optlen));
+}
+
+/**
+ * See header
+ */
+#undef setsockopt
+int windows_setsockopt(int sockfd, int level, int optname,
+					   const void *optval, socklen_t optlen)
+{
+	return wserr(setsockopt(sockfd, level, optname, optval, optlen));
+}
+
+/**
+ * See header
+ */
+#undef socket
+int windows_socket(int domain, int type, int protocol)
+{
+	return wserr(socket(domain, type, protocol));
+}
+
+/**
+ * See header
+ */
+#undef select
+int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
+				   fd_set *exceptfds, struct timeval *timeout)
+{
+	return wserr(select(nfds, readfds, writefds, exceptfds, timeout));
+}
+
+/**
+ * See header
+ */
+#undef close
+int windows_close(int fd)
+{
+	int ret;
+
+	ret = close(fd);
+	if (ret == -1 && errno == EBADF)
+	{	/* Winsock socket? */
+		ret = wserr(closesocket(fd));
+	}
+	return ret;
+}
+
+/**
+ * See header
+ */
+#undef recv
+ssize_t windows_recv(int sockfd, void *buf, size_t len, int flags)
+{
+	u_long on = 1, off = 0;
+	ssize_t outlen = -1;
+
+	if (!check_dontwait(&flags))
+	{
+		return wserr(recv(sockfd, buf, len, flags));
+	}
+	if (wserr(ioctlsocket(sockfd, FIONBIO, &on) == 0))
+	{
+		outlen = wserr(recv(sockfd, buf, len, flags));
+		ioctlsocket(sockfd, FIONBIO, &off);
+	}
+	return outlen;
+}
+
+/**
+ * See header
+ */
+#undef recvfrom
+ssize_t windows_recvfrom(int sockfd, void *buf, size_t len, int flags,
+						 struct sockaddr *src_addr, socklen_t *addrlen)
+{
+	u_long on = 1, off = 0;
+	ssize_t outlen = -1;
+
+	if (!check_dontwait(&flags))
+	{
+		return wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
+	}
+	if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
+	{
+		outlen = wserr(recvfrom(sockfd, buf, len, flags, src_addr, addrlen));
+		ioctlsocket(sockfd, FIONBIO, &off);
+	}
+	return outlen;
+}
+
+/**
+ * See header
+ */
+#undef send
+ssize_t windows_send(int sockfd, const void *buf, size_t len, int flags)
+{
+	u_long on = 1, off = 0;
+	ssize_t outlen = -1;
+
+	if (!check_dontwait(&flags))
+	{
+		return wserr(send(sockfd, buf, len, flags));
+	}
+	if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
+	{
+		outlen = wserr(send(sockfd, buf, len, flags));
+		ioctlsocket(sockfd, FIONBIO, &off);
+	}
+	return outlen;
+}
+
+/**
+ * See header
+ */
+#undef sendto
+ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
+					   const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+	u_long on = 1, off = 0;
+	ssize_t outlen = -1;
+
+	if (!check_dontwait(&flags))
+	{
+		return wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
+	}
+	if (wserr(ioctlsocket(sockfd, FIONBIO, &on)) == 0)
+	{
+		outlen = wserr(sendto(sockfd, buf, len, flags, dest_addr, addrlen));
+		ioctlsocket(sockfd, FIONBIO, &off);
+	}
+	return outlen;
+}
diff --git a/src/libstrongswan/utils/windows.h b/src/libstrongswan/utils/windows.h
new file mode 100644
index 0000000..3761e10
--- /dev/null
+++ b/src/libstrongswan/utils/windows.h
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2013 Martin Willi
+ * Copyright (C) 2013 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.
+ */
+
+/**
+ * @defgroup windows windows
+ * @{ @ingroup utils
+ */
+
+#ifndef WINDOWS_H_
+#define WINDOWS_H_
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <direct.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/* undef Windows variants evaluating values more than once */
+#undef min
+#undef max
+
+/* interface is defined as an alias to "struct" in basetypes.h, but
+ * we use it here and there as ordinary identifier. */
+#undef interface
+
+/* used by Windows API, but we have our own */
+#undef CALLBACK
+
+/* UID/GID types for capabilities, even if not supported */
+typedef u_int uid_t;
+typedef u_int gid_t;
+
+/**
+ * Initialize Windows libraries
+ */
+void windows_init();
+
+/**
+ * Deinitialize windows libraries
+ */
+void windows_deinit();
+
+/**
+ * Replacement for random(3)
+ */
+static inline long random(void)
+{
+	return rand();
+}
+
+/**
+ * Replacement for srandom(3)
+ */
+static inline void srandom(unsigned int seed)
+{
+	srand(seed);
+}
+
+/**
+ * Replacement of sched_yield(2) from <sched.h>
+ */
+static inline int sched_yield(void)
+{
+	Sleep(0);
+	return 0;
+}
+
+/**
+ * Replacement of sleep(3), cancellable by thread_cancel()
+ */
+#define sleep sleep_cancellable
+static inline int sleep_cancellable(unsigned int seconds)
+{
+	SleepEx(seconds * 1000, TRUE);
+	return 0;
+}
+
+/**
+ * Replacement of usleep(3), cancellable, ms resolution only
+ */
+int usleep(useconds_t usec);
+
+/**
+ * strdup(3), the Windows variant can't free(strdup("")) and others
+ */
+#define strdup strdup_windows
+static inline char* strdup_windows(const char *src)
+{
+	size_t len;
+	char *dst;
+
+	len = strlen(src) + 1;
+	dst = malloc(len);
+	memcpy(dst, src, len);
+	return dst;
+}
+
+/**
+ * strndup(3)
+ */
+char* strndup(const char *s, size_t n);
+
+/**
+ * Provided via ws2_32
+ */
+#ifndef InetNtop
+const char WINAPI *inet_ntop(int af, const void *src, char *dst, socklen_t size);
+#endif
+
+/**
+ * Provided via ws2_32
+ */
+#ifndef InetPton
+int WINAPI inet_pton(int af, const char *src, void *dst);
+#endif
+
+/**
+ * Provided by printf hook backend
+ */
+int asprintf(char **strp, const char *fmt, ...);
+
+/**
+ * Provided by printf hook backend
+ */
+int vasprintf(char **strp, const char *fmt, va_list ap);
+
+/**
+ * timeradd(3) from <sys/time.h>
+ */
+static inline void timeradd(struct timeval *a, struct timeval *b,
+							struct timeval *res)
+{
+	res->tv_sec = a->tv_sec + b->tv_sec;
+	res->tv_usec = a->tv_usec + b->tv_usec;
+	if (res->tv_usec >= 1000000)
+	{
+		res->tv_usec -= 1000000;
+		res->tv_sec++;
+	}
+}
+
+/**
+ * timersub(3) from <sys/time.h>
+ */
+static inline void timersub(struct timeval *a, struct timeval *b,
+							struct timeval *res)
+{
+	res->tv_sec = a->tv_sec - b->tv_sec;
+	res->tv_usec = a->tv_usec - b->tv_usec;
+	if (res->tv_usec < 0)
+	{
+		res->tv_usec += 1000000;
+		res->tv_sec--;
+	}
+}
+
+/**
+ * gmtime_r(3) from <time.h>
+ */
+static inline struct tm *gmtime_r(const time_t *timep, struct tm *result)
+{
+	struct tm *ret;
+
+	/* gmtime_s() and friends seem not to be implemented/functioning.
+	 * Relying on gmtime() on Windows works as well, as it uses thread
+	 * specific buffers. */
+	ret = gmtime(timep);
+	if (ret)
+	{
+		memcpy(result, ret, sizeof(*result));
+	}
+	return ret;
+}
+
+/**
+ * localtime_r(3) from <time.h>
+ */
+static inline struct tm *localtime_r(const time_t *timep, struct tm *result)
+{
+	struct tm *ret;
+
+	/* localtime_s() and friends seem not to be implemented/functioning.
+	 * Relying on localtime() on Windows works as well, as it uses thread
+	 * specific buffers. */
+	ret = localtime(timep);
+	if (ret)
+	{
+		memcpy(result, ret, sizeof(*result));
+	}
+	return ret;
+}
+
+/**
+ * setenv(3) from <stdlib.h>, overwrite flag is ignored
+ */
+static inline int setenv(const char *name, const char *value, int overwrite)
+{
+	if (SetEnvironmentVariableA(name, value) == 0)
+	{	/* failed */
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Lazy binding, ignored on Windows
+ */
+#define RTLD_LAZY 1
+
+/**
+ * Default handle targeting .exe
+ */
+#define RTLD_DEFAULT (NULL)
+
+/**
+ * Find symbol in next library
+ */
+#define RTLD_NEXT ((void*)~(uintptr_t)0)
+
+/**
+ * dlopen(3) from <dlfcn.h>
+ */
+void* dlopen(const char *filename, int flag);
+
+/**
+ * dlsym() from <dlfcn.h>
+ */
+void* dlsym(void *handle, const char *symbol);
+
+/**
+ * dlerror(3) from <dlfcn.h>, currently not thread save
+ */
+char* dlerror(void);
+
+/**
+ * dlclose() from <dlfcn.h>
+ */
+int dlclose(void *handle);
+
+/**
+ * socketpair(2) for SOCK_STREAM, uses TCP on loopback
+ */
+int socketpair(int domain, int type, int protocol, int sv[2]);
+
+/**
+ * getpass(3) on Windows consoles
+ */
+char* getpass(const char *prompt);
+#define HAVE_GETPASS
+
+/**
+ * Map MSG_DONTWAIT to the reserved, but deprecated MSG_INTERRUPT
+ */
+#define MSG_DONTWAIT MSG_INTERRUPT
+
+/**
+ * shutdown(2) "how"-aliases, to use Unix variant on Windows
+ */
+#define SHUT_RD SD_RECEIVE
+#define SHUT_WR SD_SEND
+#define SHUT_RDWR SD_BOTH
+
+/**
+ * shutdown(2) setting errno
+ */
+#define shutdown windows_shutdown
+int windows_shutdown(int sockfd, int how);
+
+/**
+ * accept(2) setting errno
+ */
+#define accept windows_accept
+int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+/**
+ * bind(2) setting errno
+ */
+#define bind windows_bind
+int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+/**
+ * connect(2) setting errno
+ */
+#define connect windows_connect
+int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+/**
+ * getsockname(2) setting errno
+ */
+#define getsockname windows_getsockname
+int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+/**
+ * getsockopt(2) setting errno
+ */
+#define getsockopt windows_getsockopt
+int windows_getsockopt(int sockfd, int level, int optname,
+					   void *optval, socklen_t *optlen);
+
+/**
+ * setsockopt(2) setting errno
+ */
+#define setsockopt windows_setsockopt
+int windows_setsockopt(int sockfd, int level, int optname,
+					   const void *optval, socklen_t optlen);
+
+/**
+ * socket(2) setting errno
+ */
+#define socket windows_socket
+int windows_socket(int domain, int type, int protocol);
+
+/**
+ * select(2) setting errno
+ */
+#define select windows_select
+int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
+				   fd_set *exceptfds, struct timeval *timeout);
+
+/**
+ * close(2) working for file handles and Winsock sockets
+ */
+#define close windows_close
+int windows_close(int fd);
+
+/**
+ * recv(2) with support for MSG_DONTWAIT
+ */
+#define recv windows_recv
+ssize_t windows_recv(int sockfd, void *buf, size_t len, int flags);
+
+/**
+ * recvfrom(2) with support for MSG_DONTWAIT
+ */
+#define recvfrom windows_recvfrom
+ssize_t windows_recvfrom(int sockfd, void *buf, size_t len, int flags,
+						 struct sockaddr *src_addr, socklen_t *addrlen);
+
+/**
+ * recvfrom(2) with support for MSG_DONTWAIT
+ */
+#define send windows_send
+ssize_t windows_send(int sockfd, const void *buf, size_t len, int flags);
+
+/**
+ * recvfrom(2) with support for MSG_DONTWAIT
+ */
+#define sendto windows_send
+ssize_t windows_sendto(int sockfd, const void *buf, size_t len, int flags,
+					   const struct sockaddr *dest_addr, socklen_t addrlen);
+
+/**
+ * Declaration missing on older WinGW
+ */
+_CRTIMP errno_t strerror_s(char *buf, size_t size, int errnum);
+
+/**
+ * strerror_s, but supporting POSIX compatibility errno >= 100
+ */
+#define strerror_s strerror_s_extended
+int strerror_s_extended(char *buf, size_t buflen, int errnum);
+
+/**
+ * strerror_r(2) replacement, XSI variant
+ */
+static inline int strerror_r(int errnum, char *buf, size_t buflen)
+{
+	return strerror_s(buf, buflen, errnum);
+}
+#define HAVE_STRERROR_R /* but not STRERROR_R_CHAR_P */
+
+/**
+ * MinGW does provide extended errno values. Windows itself knowns them
+ * for POSIX compatibility; we define them as well.
+ */
+#ifndef EADDRINUSE
+#define EADDRINUSE			100
+#endif
+#ifndef EADDRNOTAVAIL
+#define EADDRNOTAVAIL		101
+#endif
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT		102
+#endif
+#ifndef EALREADY
+#define EALREADY			103
+#endif
+#ifndef EBADMSG
+#define EBADMSG				104
+#endif
+#ifndef ECANCELED
+#define ECANCELED			105
+#endif
+#ifndef ECONNABORTED
+#define ECONNABORTED		106
+#endif
+#ifndef ECONNREFUSED
+#define ECONNREFUSED		107
+#endif
+#ifndef ECONNRESET
+#define ECONNRESET			108
+#endif
+#ifndef EDESTADDRREQ
+#define EDESTADDRREQ		109
+#endif
+#ifndef EHOSTUNREACH
+#define EHOSTUNREACH		110
+#endif
+#ifndef EIDRM
+#define EIDRM				111
+#endif
+#ifndef EINPROGRESS
+#define EINPROGRESS			112
+#endif
+#ifndef EISCONN
+#define EISCONN				113
+#endif
+#ifndef ELOOP
+#define ELOOP				114
+#endif
+#ifndef EMSGSIZE
+#define EMSGSIZE			115
+#endif
+#ifndef ENETDOWN
+#define ENETDOWN			116
+#endif
+#ifndef ENETRESET
+#define ENETRESET			117
+#endif
+#ifndef ENETUNREACH
+#define ENETUNREACH			118
+#endif
+#ifndef ENOBUFS
+#define ENOBUFS				119
+#endif
+#ifndef ENODATA
+#define ENODATA				120
+#endif
+#ifndef ENOLINK
+#define ENOLINK				121
+#endif
+#ifndef ENOMSG
+#define ENOMSG				122
+#endif
+#ifndef ENOPROTOOPT
+#define ENOPROTOOPT			123
+#endif
+#ifndef ENOSR
+#define ENOSR				124
+#endif
+#ifndef ENOSTR
+#define ENOSTR				125
+#endif
+#ifndef ENOTCONN
+#define ENOTCONN			126
+#endif
+#ifndef ENOTRECOVERABLE
+#define ENOTRECOVERABLE		127
+#endif
+#ifndef ENOTSOCK
+#define ENOTSOCK			128
+#endif
+#ifndef ENOTSUP
+#define ENOTSUP				129
+#endif
+#ifndef EOPNOTSUPP
+#define EOPNOTSUPP			130
+#endif
+#ifndef EOTHER
+#define EOTHER				131
+#endif
+#ifndef EOVERFLOW
+#define EOVERFLOW			132
+#endif
+#ifndef EOWNERDEAD
+#define EOWNERDEAD			133
+#endif
+#ifndef EPROTO
+#define EPROTO				134
+#endif
+#ifndef EPROTONOSUPPORT
+#define EPROTONOSUPPORT		135
+#endif
+#ifndef EPROTOTYPE
+#define EPROTOTYPE			136
+#endif
+#ifndef ETIME
+#define ETIME				137
+#endif
+#ifndef ETIMEDOUT
+#define ETIMEDOUT			138
+#endif
+#ifndef ETXTBSY
+#define ETXTBSY				139
+#endif
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK			140
+#endif
+
+
+/* Windows does not support "ll" format printf length modifiers. Mingw
+ * therefore maps these to the Windows specific I64 length modifier. That
+ * won't work for us, as we use our own printf backend on Windows, which works
+ * just fine with "ll". */
+#undef PRId64
+#define PRId64 "lld"
+#undef PRId64
+#define PRId64 "lld"
+#undef PRIdLEAST64
+#define PRIdLEAST64 "lld"
+#undef PRIdFAST64
+#define PRIdFAST64 "lld"
+#undef PRIdMAX
+#define PRIdMAX "lld"
+#undef PRIi64
+#define PRIi64 "lli"
+#undef PRIiLEAST64
+#define PRIiLEAST64 "lli"
+#undef PRIiFAST64
+#define PRIiFAST64 "lli"
+#undef PRIiMAX
+#define PRIiMAX "lli"
+#undef PRIo64
+#define PRIo64 "llo"
+#undef PRIoLEAST64
+#define PRIoLEAST64 "llo"
+#undef PRIoFAST64
+#define PRIoFAST64 "llo"
+#undef PRIoMAX
+#define PRIoMAX "llo"
+#undef PRIu64
+#define PRIu64 "llu"
+#undef PRIuLEAST64
+#define PRIuLEAST64 "llu"
+#undef PRIuFAST64
+#define PRIuFAST64 "llu"
+#undef PRIuMAX
+#define PRIuMAX "llu"
+#undef PRIx64
+#define PRIx64 "llx"
+#undef PRIxLEAST64
+#define PRIxLEAST64 "llx"
+#undef PRIxFAST64
+#define PRIxFAST64 "llx"
+#undef PRIxMAX
+#define PRIxMAX "llx"
+#undef PRIX64
+#define PRIX64 "llX"
+#undef PRIXLEAST64
+#define PRIXLEAST64 "llX"
+#undef PRIXFAST64
+#define PRIXFAST64 "llX"
+#undef PRIXMAX
+#define PRIXMAX "llX"
+
+#ifdef _WIN64
+# undef PRIdPTR
+# define PRIdPTR "lld"
+# undef PRIiPTR
+# define PRIiPTR "lli"
+# undef PRIoPTR
+# define PRIoPTR "llo"
+# undef PRIuPTR
+# define PRIuPTR "llu"
+# undef PRIxPTR
+# define PRIxPTR "llx"
+# undef PRIXPTR
+# define PRIXPTR "llX"
+#endif /* _WIN64 */
+
+#endif /** WINDOWS_H_ @}*/
diff --git a/src/libtls/Makefile.am b/src/libtls/Makefile.am
index d565a14..b649636 100644
--- a/src/libtls/Makefile.am
+++ b/src/libtls/Makefile.am
@@ -14,6 +14,10 @@ libtls_la_SOURCES = \
 libtls_la_LIBADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la
 
+if USE_WINDOWS
+  libtls_la_LIBADD += -lws2_32
+endif
+
 if USE_DEV_HEADERS
 tls_includedir = ${dev_headers}/tls
 nobase_tls_include_HEADERS = \
diff --git a/src/libtls/Makefile.in b/src/libtls/Makefile.in
index b6abd1e..85f13d0 100644
--- a/src/libtls/Makefile.in
+++ b/src/libtls/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -79,6 +79,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
+ at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
 subdir = src/libtls
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp $(am__nobase_tls_include_HEADERS_DIST)
@@ -129,8 +130,10 @@ am__uninstall_files_from_dir = { \
 am__installdirs = "$(DESTDIR)$(ipseclibdir)" \
 	"$(DESTDIR)$(tls_includedir)"
 LTLIBRARIES = $(ipseclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
 libtls_la_DEPENDENCIES =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(am__DEPENDENCIES_1)
 am_libtls_la_OBJECTS = tls_protection.lo tls_compression.lo \
 	tls_fragmentation.lo tls_alert.lo tls_crypto.lo tls_prf.lo \
 	tls_socket.lo tls_eap.lo tls_cache.lo tls_peer.lo \
@@ -312,6 +315,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -330,6 +334,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -357,6 +362,7 @@ 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@
@@ -448,6 +454,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -471,9 +478,8 @@ libtls_la_SOURCES = \
 	tls_aead_expl.c tls_aead_impl.c tls_aead_null.c tls_aead.c \
 	tls_server.c tls.c
 
-libtls_la_LIBADD = \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
-
+libtls_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(am__append_1)
 @USE_DEV_HEADERS_TRUE at tls_includedir = ${dev_headers}/tls
 @USE_DEV_HEADERS_TRUE at nobase_tls_include_HEADERS = \
 @USE_DEV_HEADERS_TRUE@	tls_protection.h tls_compression.h tls_fragmentation.h tls_alert.h \
diff --git a/src/libtls/tests/Makefile.am b/src/libtls/tests/Makefile.am
index 1c0e2f9..456383f 100644
--- a/src/libtls/tests/Makefile.am
+++ b/src/libtls/tests/Makefile.am
@@ -11,7 +11,7 @@ tls_tests_CFLAGS = \
 	-I$(top_srcdir)/src/libtls \
 	-I$(top_srcdir)/src/libstrongswan \
 	-I$(top_srcdir)/src/libstrongswan/tests \
-	-DPLUGINDIR=\""$(top_builddir)/src/libstrongswan/plugins\"" \
+	-DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
 	-DPLUGINS=\""${s_plugins}\"" \
 	@COVERAGE_CFLAGS@
 
diff --git a/src/libtls/tests/Makefile.in b/src/libtls/tests/Makefile.in
index 0b8ba33..bbc3649 100644
--- a/src/libtls/tests/Makefile.in
+++ b/src/libtls/tests/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -260,6 +260,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -278,6 +279,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -305,6 +307,7 @@ 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@
@@ -396,6 +399,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -415,7 +419,7 @@ tls_tests_CFLAGS = \
 	-I$(top_srcdir)/src/libtls \
 	-I$(top_srcdir)/src/libstrongswan \
 	-I$(top_srcdir)/src/libstrongswan/tests \
-	-DPLUGINDIR=\""$(top_builddir)/src/libstrongswan/plugins\"" \
+	-DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
 	-DPLUGINS=\""${s_plugins}\"" \
 	@COVERAGE_CFLAGS@
 
diff --git a/src/libtls/tls.c b/src/libtls/tls.c
index 6e29558..6a8d503 100644
--- a/src/libtls/tls.c
+++ b/src/libtls/tls.c
@@ -172,14 +172,14 @@ struct private_tls_t {
 	size_t outpos;
 
 	/**
-	 * Partial TLS record header received
+	 * Position in partially received record header
 	 */
-	tls_record_t head;
+	size_t headpos;
 
 	/**
-	 * Position in partially received record header
+	 * Partial TLS record header received
 	 */
-	size_t headpos;
+	tls_record_t head;
 };
 
 /**
diff --git a/src/libtls/tls_crypto.c b/src/libtls/tls_crypto.c
index 4f67b20..2cffeb8 100644
--- a/src/libtls/tls_crypto.c
+++ b/src/libtls/tls_crypto.c
@@ -959,8 +959,8 @@ static void filter_specific_config_suites(private_tls_crypto_t *this,
 			enumerator = enumerator_create_token(config, ",", " ");
 			while (enumerator->enumerate(enumerator, &token))
 			{
-				suite = enum_from_name(tls_cipher_suite_names, token);
-				if (suite == suites[i].suite)
+				if (enum_from_name(tls_cipher_suite_names, token, &suite) &&
+					suite == suites[i].suite)
 				{
 					suites[remaining++] = suites[i];
 					break;
diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c
index 68cebb9..ebe5bc3 100644
--- a/src/libtls/tls_eap.c
+++ b/src/libtls/tls_eap.c
@@ -47,7 +47,7 @@ struct private_tls_eap_t {
 	/**
 	 * Current value of EAP identifier
 	 */
-	u_int8_t identifier;
+	uint8_t identifier;
 
 	/**
 	 * TLS stack
@@ -60,6 +60,11 @@ struct private_tls_eap_t {
 	bool is_server;
 
 	/**
+	 * Supported version of the EAP tunnel protocol
+	 */
+	uint8_t supported_version;
+
+	/**
 	 * If FALSE include the total length of an EAP message
 	 * in the first fragment of fragmented messages only.
 	 * If TRUE also include the length in non-fragmented messages.
@@ -94,22 +99,24 @@ typedef enum {
 	EAP_TLS_LENGTH = (1<<7),		/* shared with EAP-TTLS/TNC/PEAP */
 	EAP_TLS_MORE_FRAGS = (1<<6),	/* shared with EAP-TTLS/TNC/PEAP */
 	EAP_TLS_START = (1<<5),			/* shared with EAP-TTLS/TNC/PEAP */
-	EAP_TTLS_VERSION = (0x07),		/* shared with EAP-TNC/PEAP      */
+	EAP_TTLS_VERSION = (0x07),		/* shared with EAP-TNC/PEAP/PT-EAP */
+	EAP_PT_START = (1<<7)			/* PT-EAP only */
 } eap_tls_flags_t;
 
-#define EAP_TTLS_SUPPORTED_VERSION	0
-#define EAP_TNC_SUPPORTED_VERSION	1
-#define EAP_PEAP_SUPPORTED_VERSION	0
+#define EAP_TTLS_SUPPORTED_VERSION		0
+#define EAP_TNC_SUPPORTED_VERSION		1
+#define EAP_PEAP_SUPPORTED_VERSION		0
+#define EAP_PT_EAP_SUPPORTED_VERSION	1
 
 /**
  * EAP-TLS/TTLS packet format
  */
 typedef struct __attribute__((packed)) {
-	u_int8_t code;
-	u_int8_t identifier;
-	u_int16_t length;
-	u_int8_t type;
-	u_int8_t flags;
+	uint8_t code;
+	uint8_t identifier;
+	uint16_t length;
+	uint8_t type;
+	uint8_t flags;
 } eap_tls_packet_t;
 
 METHOD(tls_eap_t, initiate, status_t,
@@ -120,18 +127,18 @@ METHOD(tls_eap_t, initiate, status_t,
 		eap_tls_packet_t pkt = {
 			.type = this->type,
 			.code = EAP_REQUEST,
-			.flags = EAP_TLS_START,
+			.flags = this->supported_version
 		};
 		switch (this->type)
 		{
+			case EAP_TLS:
 			case EAP_TTLS:
-				pkt.flags |= EAP_TTLS_SUPPORTED_VERSION;
-				break;
 			case EAP_TNC:
-				pkt.flags |= EAP_TNC_SUPPORTED_VERSION;
-				break;
 			case EAP_PEAP:
-				pkt.flags |= EAP_PEAP_SUPPORTED_VERSION;
+				pkt.flags |= EAP_TLS_START;
+				break;
+			case EAP_PT_EAP:
+				pkt.flags |= EAP_PT_START;
 				break;
 			default:
 				break;
@@ -153,13 +160,25 @@ METHOD(tls_eap_t, initiate, status_t,
  */
 static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
 {
-	u_int16_t pkt_len;
-	u_int32_t msg_len;
+	uint8_t version;
+	uint16_t pkt_len;
+	uint32_t msg_len;
 	size_t msg_len_offset = 0;
 
+	/* EAP-TLS doesn't have a version field */
+	if (this->type != EAP_TLS)
+	{
+		version = pkt->flags & EAP_TTLS_VERSION;
+		if (version != this->supported_version)
+		{
+			DBG1(DBG_TLS, "received %N packet with unsupported version v%u",
+			eap_type_names, this->type, version);
+			return FAILED;
+		}
+	}
 	pkt_len = untoh16(&pkt->length);
 
-	if (pkt->flags & EAP_TLS_LENGTH)
+	if (this->type != EAP_PT_EAP && (pkt->flags & EAP_TLS_LENGTH))
 	{
 		if (pkt_len < sizeof(eap_tls_packet_t) + sizeof(msg_len))
 		{
@@ -200,27 +219,12 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
 	pkt->code = this->is_server ? EAP_REQUEST : EAP_RESPONSE;
 	pkt->identifier = this->identifier;
 	pkt->type = this->type;
-	pkt->flags = 0;
-
-	switch (this->type)
-	{
-		case EAP_TTLS:
-			pkt->flags |= EAP_TTLS_SUPPORTED_VERSION;
-			break;
-		case EAP_TNC:
-			pkt->flags |= EAP_TNC_SUPPORTED_VERSION;
-			break;
-		case EAP_PEAP:
-			pkt->flags |= EAP_PEAP_SUPPORTED_VERSION;
-			break;
-		default:
-			break;
-	}
+	pkt->flags = this->supported_version;
 
 	if (this->first_fragment)
 	{
-		len = sizeof(buf) - sizeof(eap_tls_packet_t) - sizeof(u_int32_t);
-		msg_len_offset = sizeof(u_int32_t);
+		len = sizeof(buf) - sizeof(eap_tls_packet_t) - sizeof(uint32_t);
+		msg_len_offset = sizeof(uint32_t);
 	}
 	else
 	{
@@ -251,7 +255,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
 				}
 				kind = "packet";
 			}
-			else if (this->type != EAP_TNC)
+			else if (this->type != EAP_TNC && this->type != EAP_PT_EAP)
 			{
 				this->first_fragment = TRUE;
 				kind = "final fragment";
@@ -269,14 +273,14 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
 		if (pkt->flags & EAP_TLS_LENGTH)
 		{
 			htoun32(pkt + 1, reclen);
-			len += sizeof(u_int32_t);
+			len += sizeof(uint32_t);
 			pkt->flags |= EAP_TLS_LENGTH;
 		}
 		else
 		{
 			/* get rid of the reserved length field */
 			memmove(buf + sizeof(eap_tls_packet_t),
-					buf + sizeof(eap_tls_packet_t) + sizeof(u_int32_t), len);
+					buf + sizeof(eap_tls_packet_t) + sizeof(uint32_t), len);
 		}
 	}
 	len += sizeof(eap_tls_packet_t);
@@ -352,10 +356,11 @@ METHOD(tls_eap_t, process, status_t,
 	}
 	DBG3(DBG_TLS, "%N payload %B", eap_type_names, this->type, &in);
 
-	if (pkt->flags & EAP_TLS_START)
+	if ((this->type == EAP_PT_EAP && (pkt->flags & EAP_PT_START)) ||
+        (pkt->flags & EAP_TLS_START))
 	{
 		if (this->type == EAP_TTLS || this->type == EAP_TNC ||
-			this->type == EAP_PEAP)
+			this->type == EAP_PEAP || this->type == EAP_PT_EAP)
 		{
 			DBG1(DBG_TLS, "%N version is v%u", eap_type_names, this->type,
 				 pkt->flags & EAP_TTLS_VERSION);
@@ -409,14 +414,14 @@ METHOD(tls_eap_t, get_msk, chunk_t,
 	return this->tls->get_eap_msk(this->tls);
 }
 
-METHOD(tls_eap_t, get_identifier, u_int8_t,
+METHOD(tls_eap_t, get_identifier, uint8_t,
 	private_tls_eap_t *this)
 {
 	return this->identifier;
 }
 
 METHOD(tls_eap_t, set_identifier, void,
-	private_tls_eap_t *this, u_int8_t identifier)
+	private_tls_eap_t *this, uint8_t identifier)
 {
 	this->identifier = identifier;
 }
@@ -452,13 +457,31 @@ tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
 		},
 		.type = type,
 		.is_server = tls->is_server(tls),
-		.first_fragment = (type != EAP_TNC),
+		.first_fragment = (type != EAP_TNC && type != EAP_PT_EAP),
 		.frag_size = frag_size,
 		.max_msg_count = max_msg_count,
 		.include_length = include_length,
 		.tls = tls,
 	);
 
+	switch (type)
+	{
+		case EAP_TTLS:
+			this->supported_version = EAP_TTLS_SUPPORTED_VERSION;
+			break;
+		case EAP_TNC:
+			this->supported_version = EAP_TNC_SUPPORTED_VERSION;
+			break;
+		case EAP_PEAP:
+			this->supported_version = EAP_PEAP_SUPPORTED_VERSION;
+			break;
+		case EAP_PT_EAP:
+			this->supported_version = EAP_PT_EAP_SUPPORTED_VERSION;
+			break;
+		default:
+			break;
+	}
+
 	if (this->is_server)
 	{
 		do
diff --git a/src/libtls/tls_eap.h b/src/libtls/tls_eap.h
index c7da832..f3fbba0 100644
--- a/src/libtls/tls_eap.h
+++ b/src/libtls/tls_eap.h
@@ -66,7 +66,7 @@ struct tls_eap_t {
 	 *
 	 * @return				identifier
 	 */
-	u_int8_t (*get_identifier)(tls_eap_t *this);
+	uint8_t (*get_identifier)(tls_eap_t *this);
 
 	/**
 	 * Set the EAP identifier to a deterministic value, overwriting
@@ -74,7 +74,7 @@ struct tls_eap_t {
 	 *
 	 * @param identifier	EAP identifier
 	 */
-	void (*set_identifier) (tls_eap_t *this, u_int8_t identifier);
+	void (*set_identifier) (tls_eap_t *this, uint8_t identifier);
 
 	/**
 	 * Destroy a tls_eap_t.
diff --git a/src/libtnccs/Makefile.am b/src/libtnccs/Makefile.am
index 22a3b93..7a630fe 100644
--- a/src/libtnccs/Makefile.am
+++ b/src/libtnccs/Makefile.am
@@ -12,6 +12,10 @@ libtnccs_la_LIBADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
 	$(top_builddir)/src/libtncif/libtncif.la
 
+if USE_WINDOWS
+  libtnccs_la_LIBADD += -lws2_32
+endif
+
 libtnccs_la_SOURCES = \
 tnc/tnc.h tnc/tnc.c \
 tnc/imc/imc.h tnc/imc/imc_manager.h \
@@ -72,5 +76,3 @@ if MONOLITHIC
   libtnccs_la_LIBADD += plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la
 endif
 endif
-
-
diff --git a/src/libtnccs/Makefile.in b/src/libtnccs/Makefile.in
index bf37bc6..d3c0196 100644
--- a/src/libtnccs/Makefile.in
+++ b/src/libtnccs/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -78,18 +78,19 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at USE_TNC_TNCCS_TRUE@am__append_1 = plugins/tnc_tnccs
- at MONOLITHIC_TRUE@@USE_TNC_TNCCS_TRUE at am__append_2 = plugins/tnc_tnccs/libstrongswan-tnc-tnccs.la
- at USE_TNC_IMC_TRUE@am__append_3 = plugins/tnc_imc
- at MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE at am__append_4 = plugins/tnc_imc/libstrongswan-tnc-imc.la
- at USE_TNC_IMV_TRUE@am__append_5 = plugins/tnc_imv
- at MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE at am__append_6 = plugins/tnc_imv/libstrongswan-tnc-imv.la
- at USE_TNCCS_11_TRUE@am__append_7 = plugins/tnccs_11
- at MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE at am__append_8 = plugins/tnccs_11/libstrongswan-tnccs-11.la
- at USE_TNCCS_20_TRUE@am__append_9 = plugins/tnccs_20
- at MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE at am__append_10 = plugins/tnccs_20/libstrongswan-tnccs-20.la
- at USE_TNCCS_DYNAMIC_TRUE@am__append_11 = plugins/tnccs_dynamic
- at MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE at am__append_12 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la
+ at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
+ at USE_TNC_TNCCS_TRUE@am__append_2 = plugins/tnc_tnccs
+ at MONOLITHIC_TRUE@@USE_TNC_TNCCS_TRUE at am__append_3 = plugins/tnc_tnccs/libstrongswan-tnc-tnccs.la
+ at USE_TNC_IMC_TRUE@am__append_4 = plugins/tnc_imc
+ at MONOLITHIC_TRUE@@USE_TNC_IMC_TRUE at am__append_5 = plugins/tnc_imc/libstrongswan-tnc-imc.la
+ at USE_TNC_IMV_TRUE@am__append_6 = plugins/tnc_imv
+ at MONOLITHIC_TRUE@@USE_TNC_IMV_TRUE at am__append_7 = plugins/tnc_imv/libstrongswan-tnc-imv.la
+ at USE_TNCCS_11_TRUE@am__append_8 = plugins/tnccs_11
+ at MONOLITHIC_TRUE@@USE_TNCCS_11_TRUE at am__append_9 = plugins/tnccs_11/libstrongswan-tnccs-11.la
+ at USE_TNCCS_20_TRUE@am__append_10 = plugins/tnccs_20
+ at MONOLITHIC_TRUE@@USE_TNCCS_20_TRUE at am__append_11 = plugins/tnccs_20/libstrongswan-tnccs-20.la
+ at USE_TNCCS_DYNAMIC_TRUE@am__append_12 = plugins/tnccs_dynamic
+ at MONOLITHIC_TRUE@@USE_TNCCS_DYNAMIC_TRUE at am__append_13 = plugins/tnccs_dynamic/libstrongswan-tnccs-dynamic.la
 subdir = src/libtnccs
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -139,11 +140,12 @@ am__uninstall_files_from_dir = { \
   }
 am__installdirs = "$(DESTDIR)$(ipseclibdir)"
 LTLIBRARIES = $(ipseclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
 libtnccs_la_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libtncif/libtncif.la $(am__append_2) \
-	$(am__append_4) $(am__append_6) $(am__append_8) \
-	$(am__append_10) $(am__append_12)
+	$(top_builddir)/src/libtncif/libtncif.la $(am__DEPENDENCIES_1) \
+	$(am__append_3) $(am__append_5) $(am__append_7) \
+	$(am__append_9) $(am__append_11) $(am__append_13)
 am__dirstamp = $(am__leading_dot)dirstamp
 am_libtnccs_la_OBJECTS = tnc/tnc.lo tnc/imv/imv_recommendations.lo \
 	tnc/tnccs/tnccs.lo tnc/tnccs/tnccs_manager.lo
@@ -318,6 +320,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -336,6 +339,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -363,6 +367,7 @@ 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@
@@ -454,6 +459,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -475,9 +481,9 @@ AM_LDFLAGS = \
 ipseclib_LTLIBRARIES = libtnccs.la
 libtnccs_la_LIBADD =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libtncif/libtncif.la $(am__append_2) \
-	$(am__append_4) $(am__append_6) $(am__append_8) \
-	$(am__append_10) $(am__append_12)
+	$(top_builddir)/src/libtncif/libtncif.la $(am__append_1) \
+	$(am__append_3) $(am__append_5) $(am__append_7) \
+	$(am__append_9) $(am__append_11) $(am__append_13)
 libtnccs_la_SOURCES = \
 tnc/tnc.h tnc/tnc.c \
 tnc/imc/imc.h tnc/imc/imc_manager.h \
@@ -487,15 +493,15 @@ tnc/tnccs/tnccs.h tnc/tnccs/tnccs.c \
 tnc/tnccs/tnccs_manager.h tnc/tnccs/tnccs_manager.c
 
 EXTRA_DIST = Android.mk
- at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_1) $(am__append_3) \
- at MONOLITHIC_FALSE@	$(am__append_5) $(am__append_7) \
- at MONOLITHIC_FALSE@	$(am__append_9) $(am__append_11)
+ at MONOLITHIC_FALSE@SUBDIRS = . $(am__append_2) $(am__append_4) \
+ at MONOLITHIC_FALSE@	$(am__append_6) $(am__append_8) \
+ at MONOLITHIC_FALSE@	$(am__append_10) $(am__append_12)
 
 # build optional plugins
 ########################
- at MONOLITHIC_TRUE@SUBDIRS = $(am__append_1) $(am__append_3) \
- at MONOLITHIC_TRUE@	$(am__append_5) $(am__append_7) \
- at MONOLITHIC_TRUE@	$(am__append_9) $(am__append_11)
+ at MONOLITHIC_TRUE@SUBDIRS = $(am__append_2) $(am__append_4) \
+ at MONOLITHIC_TRUE@	$(am__append_6) $(am__append_8) \
+ at MONOLITHIC_TRUE@	$(am__append_10) $(am__append_12)
 all: all-recursive
 
 .SUFFIXES:
diff --git a/src/libtnccs/plugins/tnc_imc/Makefile.am b/src/libtnccs/plugins/tnc_imc/Makefile.am
index b2c26cb..5e18104 100644
--- a/src/libtnccs/plugins/tnc_imc/Makefile.am
+++ b/src/libtnccs/plugins/tnc_imc/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-tnc-imc.la
diff --git a/src/libtnccs/plugins/tnc_imc/Makefile.in b/src/libtnccs/plugins/tnc_imc/Makefile.in
index 11a3952..3ba06f9 100644
--- a/src/libtnccs/plugins/tnc_imc/Makefile.in
+++ b/src/libtnccs/plugins/tnc_imc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnc-imc.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-tnc-imc.la
diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc.c b/src/libtnccs/plugins/tnc_imc/tnc_imc.c
index 2d556d9..623da7f 100644
--- a/src/libtnccs/plugins/tnc_imc/tnc_imc.c
+++ b/src/libtnccs/plugins/tnc_imc/tnc_imc.c
@@ -15,7 +15,9 @@
 
 #include "tnc_imc.h"
 
+#ifndef WIN32
 #include <dlfcn.h>
+#endif
 
 #include <tncif_pa_subtypes.h>
 
@@ -95,7 +97,7 @@ METHOD(imc_t, add_id, void,
 	void *pointer;
 
 	/* store the scalar value in the pointer */
-	pointer = (void*)id;
+	pointer = (void*)(uintptr_t)id;
 	this->additional_ids->insert_last(this->additional_ids, pointer);
 }
 
@@ -124,7 +126,7 @@ METHOD(imc_t, has_id, bool,
 	while (enumerator->enumerate(enumerator, &pointer))
 	{
 		/* interpret pointer as scalar value */
-		additional_id = (TNC_UInt32)pointer;
+		additional_id = (uintptr_t)pointer;
 
 		if (id == additional_id)
 		{
diff --git a/src/libtnccs/plugins/tnc_imv/Makefile.am b/src/libtnccs/plugins/tnc_imv/Makefile.am
index 0541d4c..8e2af63 100644
--- a/src/libtnccs/plugins/tnc_imv/Makefile.am
+++ b/src/libtnccs/plugins/tnc_imv/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-tnc-imv.la
diff --git a/src/libtnccs/plugins/tnc_imv/Makefile.in b/src/libtnccs/plugins/tnc_imv/Makefile.in
index cef45ab..97c05c1 100644
--- a/src/libtnccs/plugins/tnc_imv/Makefile.in
+++ b/src/libtnccs/plugins/tnc_imv/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -269,6 +269,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -287,6 +288,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -314,6 +316,7 @@ 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@
@@ -405,6 +408,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -422,7 +426,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtls
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnc-imv.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-tnc-imv.la
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv.c b/src/libtnccs/plugins/tnc_imv/tnc_imv.c
index ab2e552..039f1fc 100644
--- a/src/libtnccs/plugins/tnc_imv/tnc_imv.c
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv.c
@@ -15,7 +15,9 @@
 
 #include "tnc_imv.h"
 
+#ifndef WIN32
 #include <dlfcn.h>
+#endif
 
 #include <tncif_pa_subtypes.h>
 
diff --git a/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c
index 5624501..1a03158 100644
--- a/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c
+++ b/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c
@@ -432,7 +432,7 @@ METHOD(imv_manager_t, destroy, void,
 imv_manager_t* tnc_imv_manager_create(void)
 {
 	private_tnc_imv_manager_t *this;
-	recommendation_policy_t policy;
+	char *polname;
 
 	INIT(this,
 		.public = {
@@ -458,11 +458,12 @@ imv_manager_t* tnc_imv_manager_create(void)
 		.next_imv_id = 1,
 	);
 
-	policy = enum_from_name(recommendation_policy_names,
-				lib->settings->get_str(lib->settings,
-					"%s.plugins.tnc-imv.recommendation_policy",
-					"default", lib->ns));
-	this->policy = (policy != -1) ? policy : RECOMMENDATION_POLICY_DEFAULT;
+	polname = lib->settings->get_str(lib->settings,
+				"%s.plugins.tnc-imv.recommendation_policy", "default", lib->ns);
+	if (!enum_from_name(recommendation_policy_names, polname, &this->policy))
+	{
+		this->policy = RECOMMENDATION_POLICY_DEFAULT;
+	}
 	DBG1(DBG_TNC, "TNC recommendation policy is '%N'",
 				   recommendation_policy_names, this->policy);
 
diff --git a/src/libtnccs/plugins/tnc_tnccs/Makefile.am b/src/libtnccs/plugins/tnc_tnccs/Makefile.am
index f16bf8e..05a854a 100644
--- a/src/libtnccs/plugins/tnc_tnccs/Makefile.am
+++ b/src/libtnccs/plugins/tnc_tnccs/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la
diff --git a/src/libtnccs/plugins/tnc_tnccs/Makefile.in b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
index bba53f5..adbbf6c 100644
--- a/src/libtnccs/plugins/tnc_tnccs/Makefile.in
+++ b/src/libtnccs/plugins/tnc_tnccs/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnc-tnccs.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-tnc-tnccs.la
diff --git a/src/libtnccs/plugins/tnccs_11/Makefile.am b/src/libtnccs/plugins/tnccs_11/Makefile.am
index cbe0b8e..fc22c46 100644
--- a/src/libtnccs/plugins/tnccs_11/Makefile.am
+++ b/src/libtnccs/plugins/tnccs_11/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS}
 
diff --git a/src/libtnccs/plugins/tnccs_11/Makefile.in b/src/libtnccs/plugins/tnccs_11/Makefile.in
index 182d1dd..92f3b08 100644
--- a/src/libtnccs/plugins/tnccs_11/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_11/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -278,6 +278,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -296,6 +297,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -323,6 +325,7 @@ 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@
@@ -414,6 +417,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -432,7 +436,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 libstrongswan_tnccs_11_la_LIBADD = ${xml_LIBS} $(am__append_1)
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnccs-11.la
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c
index 86b7c6a..26a6c03 100644
--- a/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_error_msg.c
@@ -128,9 +128,8 @@ tnccs_msg_t *tnccs_error_msg_create_from_node(xmlNodePtr node)
 	error_type_name = xmlGetProp(node, "type");
 	if (error_type_name)
 	{
-		this->error_type = enum_from_name(tnccs_error_type_names,
-										  error_type_name);
-		if (this->error_type == -1)
+		if (!enum_from_name(tnccs_error_type_names, error_type_name,
+							&this->error_type))
 		{
 			this->error_type = TNCCS_ERROR_OTHER;
 		}
diff --git a/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c b/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c
index fa5ce82..e373656 100644
--- a/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c
+++ b/src/libtnccs/plugins/tnccs_11/messages/tnccs_msg.c
@@ -41,7 +41,7 @@ tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
 	char *error_msg, buf[BUF_LEN];
 	tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
 	tnccs_msg_t *msg;
-	tnccs_msg_type_t type = IMC_IMV_MSG;
+	tnccs_msg_type_t type = IMC_IMV_MSG, nametype;
 
 	if (streq((char*)node->name, "IMC-IMV-Message"))
 	{
@@ -103,7 +103,8 @@ tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
 				error_msg = "node is not in the TNCCS message namespace";
 				goto fatal;
 			}
-			if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name))
+			if (!enum_from_name(tnccs_msg_type_names, cur->name, &nametype) ||
+				type != nametype)
 			{
 				error_msg = buf;
 				snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'",
@@ -137,4 +138,3 @@ fatal:
 	errors->insert_last(errors, msg);
 	return NULL;
 }
-
diff --git a/src/libtnccs/plugins/tnccs_20/Makefile.am b/src/libtnccs/plugins/tnccs_20/Makefile.am
index f64526e..2aefecd 100644
--- a/src/libtnccs/plugins/tnccs_20/Makefile.am
+++ b/src/libtnccs/plugins/tnccs_20/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-tnccs-20.la
diff --git a/src/libtnccs/plugins/tnccs_20/Makefile.in b/src/libtnccs/plugins/tnccs_20/Makefile.in
index 468f217..230440b 100644
--- a/src/libtnccs/plugins/tnccs_20/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_20/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -279,6 +279,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -297,6 +298,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -324,6 +326,7 @@ 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@
@@ -415,6 +418,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -432,7 +436,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnccs-20.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-tnccs-20.la
diff --git a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
index ef0faf2..228c082 100644
--- a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
+++ b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
@@ -16,6 +16,7 @@
 
 #include "pb_tnc_batch.h"
 #include "messages/ietf/pb_error_msg.h"
+#include "messages/ietf/pb_pa_msg.h"
 #include "state_machine/pb_tnc_state_machine.h"
 
 #include <tnc/tnccs/tnccs.h>
@@ -51,7 +52,6 @@ typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t;
 
 #define PB_TNC_BATCH_FLAG_NONE		0x00
 #define PB_TNC_BATCH_FLAG_D			(1<<7)
-#define PB_TNC_BATCH_HEADER_SIZE	8
 
 /**
  *   PB-TNC Message (see section 4.2 of RFC 5793)
@@ -71,7 +71,6 @@ typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t;
 
 #define PB_TNC_FLAG_NONE			0x00
 #define PB_TNC_FLAG_NOSKIP			(1<<7)
-#define PB_TNC_HEADER_SIZE			12
 
 #define PB_TNC_RESERVED_MSG_TYPE	0xffffffff
 
@@ -148,7 +147,7 @@ METHOD(pb_tnc_batch_t, add_msg, bool,
 
 	msg->build(msg);
 	msg_value = msg->get_encoding(msg);
-	msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
+	msg_len = PB_TNC_MSG_HEADER_SIZE + msg_value.len;
 
 	if (this->batch_len + msg_len > this->max_batch_len)
 	{
@@ -201,7 +200,7 @@ METHOD(pb_tnc_batch_t, build, void,
 
 		/* build PB-TNC message */
 		msg_value = msg->get_encoding(msg);
-		msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
+		msg_len = PB_TNC_MSG_HEADER_SIZE + msg_value.len;
 		msg_type = msg->get_type(msg);
 		switch (msg_type.vendor_id)
 		{
@@ -339,7 +338,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
 
 	data = chunk_skip(this->encoding, this->offset);
 
-	if (data.len < PB_TNC_HEADER_SIZE)
+	if (data.len < PB_TNC_MSG_HEADER_SIZE)
 	{
 		DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header",
 					  data.len);
@@ -403,7 +402,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
 	}
 	else
 	{
-		if (msg_len < PB_TNC_HEADER_SIZE)
+		if (msg_len < PB_TNC_MSG_HEADER_SIZE)
 		{
 			DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length",
 						   msg_len);
@@ -475,7 +474,7 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
 	DBG2(DBG_TNC, "processing %N/%N message (%u bytes)", pen_names, vendor_id,
 		 msg_type_names, msg_type, msg_len);
 	data.len = msg_len;
-	msg_value = chunk_skip(data, PB_TNC_HEADER_SIZE);
+	msg_value = chunk_skip(data, PB_TNC_MSG_HEADER_SIZE);
 	msg_pen_type = pen_type_create(vendor_id, msg_type);
 	pb_tnc_msg = pb_tnc_msg_create_from_data(msg_pen_type, msg_value);
 
diff --git a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
index 60cef77..106c557 100644
--- a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
+++ b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.h
@@ -29,6 +29,9 @@ typedef struct pb_tnc_batch_t pb_tnc_batch_t;
 
 #include <library.h>
 
+#define PB_TNC_BATCH_HEADER_SIZE	 8
+#define PB_TNC_MSG_HEADER_SIZE		12
+
 /**
   * PB-TNC Batch Types as defined in section 4.1 of RFC 5793
  */
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c
index a9a097b..263af32 100644
--- a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.c
@@ -117,7 +117,7 @@ METHOD(pb_tnc_msg_t, build, void,
 	}
 
 	/* build message header */
-	writer = bio_writer_create(64);
+	writer = bio_writer_create(PB_PA_MSG_HEADER_SIZE);
 	writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE);
 	writer->write_uint24(writer, this->subtype.vendor_id);
 	writer->write_uint32(writer, this->subtype.type);
diff --git a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h
index 093bb45..f3b6b15 100644
--- a/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h
+++ b/src/libtnccs/plugins/tnccs_20/messages/ietf/pb_pa_msg.h
@@ -27,6 +27,8 @@ typedef struct pb_pa_msg_t pb_pa_msg_t;
 
 #include <pen/pen.h>
 
+#define PB_PA_MSG_HEADER_SIZE	12
+
 /**
  * Class representing the PB-PA message type.
  */
diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20.c b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
index f78b85a..dc4da51 100644
--- a/src/libtnccs/plugins/tnccs_20/tnccs_20.c
+++ b/src/libtnccs/plugins/tnccs_20/tnccs_20.c
@@ -1032,6 +1032,38 @@ tnccs_t* tnccs_20_create(bool is_server,
 						 tnc_ift_type_t transport, tnccs_cb_t cb)
 {
 	private_tnccs_20_t *this;
+	size_t max_batch_size, default_max_batch_size;
+	size_t max_message_size, default_max_message_size;
+
+	/* Determine the maximum PB-TNC batch size and PA-TNC message size */
+	switch (transport)
+	{
+		case TNC_IFT_TLS_2_0:
+		case TNC_IFT_TLS_1_0:
+			default_max_batch_size = 128 * TLS_MAX_FRAGMENT_LEN - 16;
+			break;
+		case TNC_IFT_EAP_2_0:
+		case TNC_IFT_EAP_1_1:
+		case TNC_IFT_EAP_1_0:
+		case TNC_IFT_UNKNOWN:
+		default:
+			default_max_batch_size =   4 * TLS_MAX_FRAGMENT_LEN - 14;
+			break;
+	}
+
+	max_batch_size = min(default_max_batch_size,
+						lib->settings->get_int(lib->settings,
+								"%s.plugins.tnccs-20.max_batch_size",
+								 default_max_batch_size, lib->ns));
+
+	default_max_message_size = max_batch_size - PB_TNC_BATCH_HEADER_SIZE
+											  - PB_TNC_MSG_HEADER_SIZE
+											  - PB_PA_MSG_HEADER_SIZE;
+
+	max_message_size = min(default_max_message_size,
+							lib->settings->get_int(lib->settings,
+								"%s.plugins.tnccs-20.max_message_size",
+								 default_max_message_size, lib->ns));
 
 	INIT(this,
 		.public = {
@@ -1062,10 +1094,8 @@ tnccs_t* tnccs_20_create(bool is_server,
 		.state_machine = pb_tnc_state_machine_create(is_server),
 		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
 		.messages = linked_list_create(),
-		.max_batch_len = lib->settings->get_int(lib->settings,
-						"%s.plugins.tnccs-20.max_batch_size", 65522, lib->ns),
-		.max_msg_len = lib->settings->get_int(lib->settings,
-						"%s.plugins.tnccs-20.max_message_size", 65490, lib->ns),
+		.max_batch_len = max_batch_size,
+		.max_msg_len = max_message_size,
 		.ref = 1,
 	);
 
diff --git a/src/libtnccs/plugins/tnccs_dynamic/Makefile.am b/src/libtnccs/plugins/tnccs_dynamic/Makefile.am
index 1a28878..23eb7f1 100644
--- a/src/libtnccs/plugins/tnccs_dynamic/Makefile.am
+++ b/src/libtnccs/plugins/tnccs_dynamic/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 if MONOLITHIC
 noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
diff --git a/src/libtnccs/plugins/tnccs_dynamic/Makefile.in b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
index 7327202..ee3f72d 100644
--- a/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
+++ b/src/libtnccs/plugins/tnccs_dynamic/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -268,6 +268,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -286,6 +287,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -313,6 +315,7 @@ 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@
@@ -404,6 +407,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,7 +425,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtnccs
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 @MONOLITHIC_TRUE at noinst_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
 @MONOLITHIC_FALSE at plugin_LTLIBRARIES = libstrongswan-tnccs-dynamic.la
diff --git a/src/libtnccs/tnc/tnc.c b/src/libtnccs/tnc/tnc.c
index e002b10..80ba61c 100644
--- a/src/libtnccs/tnc/tnc.c
+++ b/src/libtnccs/tnc/tnc.c
@@ -26,6 +26,12 @@
 #include <utils/lexparser.h>
 #include <utils/debug.h>
 
+#ifdef WIN32
+# define DEFAULT_TNC_CONFIG "tnc_config"
+#else
+# define DEFAULT_TNC_CONFIG "/etc/tnc_config"
+#endif
+
 typedef struct private_tnc_t private_tnc_t;
 
 typedef tnccs_manager_t *(*tnc_create_tnccs_manager_t)(void);
@@ -251,7 +257,7 @@ bool tnc_manager_register(plugin_t *plugin, plugin_feature_t *feature,
 		{
 			load_imcvs_from_config(
 						lib->settings->get_str(lib->settings,
-								"%s.tnc.tnc_config", "/etc/tnc_config", lib->ns),
+							"%s.tnc.tnc_config", DEFAULT_TNC_CONFIG, lib->ns),
 						is_imc);
 		}
 	}
diff --git a/src/libtncif/Makefile.in b/src/libtncif/Makefile.in
index de76a6e..ee54a68 100644
--- a/src/libtncif/Makefile.in
+++ b/src/libtncif/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -230,6 +230,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -248,6 +249,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -275,6 +277,7 @@ 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@
@@ -366,6 +369,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/manager/Makefile.am b/src/manager/Makefile.am
index 41001dd..a4f151c 100644
--- a/src/manager/Makefile.am
+++ b/src/manager/Makefile.am
@@ -22,7 +22,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 # Don't forget to add templates to EXTRA_DIST !!! How to automate?
 manager_templatesdir = ${managerdir}/templates
diff --git a/src/manager/Makefile.in b/src/manager/Makefile.in
index 04db569..0057526 100644
--- a/src/manager/Makefile.in
+++ b/src/manager/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -282,6 +282,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -300,6 +301,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -327,6 +329,7 @@ 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@
@@ -418,6 +421,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -447,7 +451,7 @@ AM_CPPFLAGS = \
 
 AM_CFLAGS = \
 	${xml_CFLAGS} \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 
 # Don't forget to add templates to EXTRA_DIST !!! How to automate?
diff --git a/src/medsrv/Makefile.am b/src/medsrv/Makefile.am
index 40bafd8..94ab0cf 100644
--- a/src/medsrv/Makefile.am
+++ b/src/medsrv/Makefile.am
@@ -18,7 +18,7 @@ AM_CPPFLAGS = \
 	-DPLUGINS=\""${medsrv_plugins}\""
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 # Don't forget to add templates to EXTRA_DIST !!! How to automate?
 medsrv_templatesdir = ${medsrvdir}/templates
diff --git a/src/medsrv/Makefile.in b/src/medsrv/Makefile.in
index d26237b..a895b02 100644
--- a/src/medsrv/Makefile.in
+++ b/src/medsrv/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -271,6 +271,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -289,6 +290,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -316,6 +318,7 @@ 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@
@@ -407,6 +410,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -432,7 +436,7 @@ AM_CPPFLAGS = \
 	-DPLUGINS=\""${medsrv_plugins}\""
 
 AM_CFLAGS = \
-	-rdynamic
+	$(PLUGIN_CFLAGS)
 
 
 # Don't forget to add templates to EXTRA_DIST !!! How to automate?
diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in
index 2dd91e8..8349a77 100644
--- a/src/pki/Makefile.in
+++ b/src/pki/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -280,6 +280,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -298,6 +299,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -325,6 +327,7 @@ 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@
@@ -416,6 +419,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/pki/command.c b/src/pki/command.c
index 075a227..13e8140 100644
--- a/src/pki/command.c
+++ b/src/pki/command.c
@@ -73,7 +73,7 @@ static void build_opts()
 	memset(command_optstring, 0, sizeof(command_optstring));
 	if (active == help_idx)
 	{
-		for (i = 0; cmds[i].cmd; i++)
+		for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
 		{
 			command_opts[i].name = cmds[i].cmd;
 			command_opts[i].val = cmds[i].op;
diff --git a/src/pki/commands/acert.c b/src/pki/commands/acert.c
index d49365d..185aa40 100644
--- a/src/pki/commands/acert.c
+++ b/src/pki/commands/acert.c
@@ -53,8 +53,7 @@ static int acert()
 			case 'h':
 				goto usage;
 			case 'g':
-				digest = enum_from_name(hash_algorithm_short_names, arg);
-				if (digest == -1)
+				if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
 				{
 					error = "invalid --digest type";
 					goto usage;
@@ -197,6 +196,7 @@ static int acert()
 	}
 	else
 	{
+		set_file_mode(stdin, CERT_ASN1_DER);
 		if (!chunk_from_fd(0, &encoding))
 		{
 			fprintf(stderr, "%s: ", strerror(errno));
@@ -233,6 +233,7 @@ static int acert()
 		error = "encoding attribute certificate failed";
 		goto end;
 	}
+	set_file_mode(stdout, form);
 	if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
 	{
 		error = "writing attribute certificate key failed";
diff --git a/src/pki/commands/gen.c b/src/pki/commands/gen.c
index b74be7d..ce28a09 100644
--- a/src/pki/commands/gen.c
+++ b/src/pki/commands/gen.c
@@ -133,6 +133,7 @@ static int gen()
 		return 1;
 	}
 	key->destroy(key);
+	set_file_mode(stdout, form);
 	if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
 	{
 		fprintf(stderr, "writing private key failed\n");
@@ -163,4 +164,3 @@ static void __attribute__ ((constructor))reg()
 		}
 	});
 }
-
diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c
index d03326e..aaa2c2f 100644
--- a/src/pki/commands/issue.c
+++ b/src/pki/commands/issue.c
@@ -106,8 +106,7 @@ static int issue()
 				}
 				continue;
 			case 'g':
-				digest = enum_from_name(hash_algorithm_short_names, arg);
-				if (digest == -1)
+				if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
 				{
 					error = "invalid --digest type";
 					goto usage;
@@ -403,6 +402,7 @@ static int issue()
 		{
 			chunk_t chunk;
 
+			set_file_mode(stdin, CERT_ASN1_DER);
 			if (!chunk_from_fd(0, &chunk))
 			{
 				fprintf(stderr, "%s: ", strerror(errno));
@@ -501,6 +501,7 @@ static int issue()
 		error = "encoding certificate failed";
 		goto end;
 	}
+	set_file_mode(stdout, form);
 	if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
 	{
 		error = "writing certificate key failed";
diff --git a/src/pki/commands/keyid.c b/src/pki/commands/keyid.c
index 64bb3cc..c3ac0c2 100644
--- a/src/pki/commands/keyid.c
+++ b/src/pki/commands/keyid.c
@@ -91,6 +91,7 @@ static int keyid()
 	{
 		chunk_t chunk;
 
+		set_file_mode(stdin, CERT_ASN1_DER);
 		if (!chunk_from_fd(0, &chunk))
 		{
 			fprintf(stderr, "reading input failed: %s\n", strerror(errno));
diff --git a/src/pki/commands/pkcs7.c b/src/pki/commands/pkcs7.c
index 6c75693..28bcd13 100644
--- a/src/pki/commands/pkcs7.c
+++ b/src/pki/commands/pkcs7.c
@@ -58,6 +58,7 @@ static bool write_to_stream(FILE *stream, chunk_t data)
 {
 	size_t len, total = 0;
 
+	set_file_mode(stream, CERT_ASN1_DER);
 	while (total < data.len)
 	{
 		len = fwrite(data.ptr + total, 1, data.len - total, stream);
diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c
index 15ace03..fb07169 100644
--- a/src/pki/commands/print.c
+++ b/src/pki/commands/print.c
@@ -604,6 +604,7 @@ static int print()
 	{
 		chunk_t chunk;
 
+		set_file_mode(stdin, CERT_ASN1_DER);
 		if (!chunk_from_fd(0, &chunk))
 		{
 			fprintf(stderr, "reading input failed: %s\n", strerror(errno));
diff --git a/src/pki/commands/pub.c b/src/pki/commands/pub.c
index 260044c..b8d2f70 100644
--- a/src/pki/commands/pub.c
+++ b/src/pki/commands/pub.c
@@ -110,6 +110,7 @@ static int pub()
 	{
 		chunk_t chunk;
 
+		set_file_mode(stdin, CERT_ASN1_DER);
 		if (!chunk_from_fd(0, &chunk))
 		{
 			fprintf(stderr, "reading input failed: %s\n", strerror(errno));
@@ -163,6 +164,7 @@ static int pub()
 		return 1;
 	}
 	public->destroy(public);
+	set_file_mode(stdout, form);
 	if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
 	{
 		fprintf(stderr, "writing public key failed\n");
diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c
index 5b2c128..0236835 100644
--- a/src/pki/commands/req.c
+++ b/src/pki/commands/req.c
@@ -64,8 +64,7 @@ static int req()
 				}
 				continue;
 			case 'g':
-				digest = enum_from_name(hash_algorithm_short_names, arg);
-				if (digest == -1)
+				if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
 				{
 					error = "invalid --digest type";
 					goto usage;
@@ -119,6 +118,7 @@ static int req()
 	{
 		chunk_t chunk;
 
+		set_file_mode(stdin, CERT_ASN1_DER);
 		if (!chunk_from_fd(0, &chunk))
 		{
 			fprintf(stderr, "reading private key failed: %s\n", strerror(errno));
@@ -151,6 +151,7 @@ static int req()
 		error = "encoding certificate request failed";
 		goto end;
 	}
+	set_file_mode(stdout, form);
 	if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
 	{
 		error = "writing certificate request failed";
diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c
index a35a42b..daefcdc 100644
--- a/src/pki/commands/self.c
+++ b/src/pki/commands/self.c
@@ -95,8 +95,7 @@ static int self()
 				}
 				continue;
 			case 'g':
-				digest = enum_from_name(hash_algorithm_short_names, arg);
-				if (digest == -1)
+				if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
 				{
 					error = "invalid --digest type";
 					goto usage;
@@ -293,6 +292,7 @@ static int self()
 	{
 		chunk_t chunk;
 
+		set_file_mode(stdin, CERT_ASN1_DER);
 		if (!chunk_from_fd(0, &chunk))
 		{
 			fprintf(stderr, "%s: ", strerror(errno));
@@ -361,6 +361,7 @@ static int self()
 		error = "encoding certificate failed";
 		goto end;
 	}
+	set_file_mode(stdout, form);
 	if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
 	{
 		error = "writing certificate key failed";
diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c
index c9eebbf..e5f49ef 100644
--- a/src/pki/commands/signcrl.c
+++ b/src/pki/commands/signcrl.c
@@ -142,8 +142,7 @@ static int sign_crl()
 			case 'h':
 				goto usage;
 			case 'g':
-				digest = enum_from_name(hash_algorithm_short_names, arg);
-				if (digest == -1)
+				if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
 				{
 					error = "invalid --digest type";
 					goto usage;
@@ -406,6 +405,7 @@ static int sign_crl()
 		error = "encoding CRL failed";
 		goto error;
 	}
+	set_file_mode(stdout, form);
 	if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
 	{
 		error = "writing CRL failed";
diff --git a/src/pki/commands/verify.c b/src/pki/commands/verify.c
index f30dda9..8cc633a 100644
--- a/src/pki/commands/verify.c
+++ b/src/pki/commands/verify.c
@@ -19,32 +19,53 @@
 
 #include <credentials/certificates/certificate.h>
 #include <credentials/certificates/x509.h>
+#include <credentials/sets/mem_cred.h>
 
 /**
  * Verify a certificate signature
  */
 static int verify()
 {
-	certificate_t *cert, *ca;
-	char *file = NULL, *cafile = NULL;
-	bool good = FALSE;
-	char *arg;
+	bool trusted = FALSE, valid = FALSE, revoked = FALSE;
+	bool has_ca = FALSE, online = FALSE;
+	certificate_t *cert;
+	enumerator_t *enumerator;
+	auth_cfg_t *auth;
+	mem_cred_t *creds;
+	char *arg, *file = NULL;
+
+	creds = mem_cred_create();
+	lib->credmgr->add_set(lib->credmgr, &creds->set);
 
 	while (TRUE)
 	{
 		switch (command_getopt(&arg))
 		{
 			case 'h':
+				creds->destroy(creds);
 				return command_usage(NULL);
 			case 'i':
 				file = arg;
 				continue;
 			case 'c':
-				cafile = arg;
+				cert = lib->creds->create(lib->creds,
+										  CRED_CERTIFICATE, CERT_X509,
+										  BUILD_FROM_FILE, arg, BUILD_END);
+				if (!cert)
+				{
+					fprintf(stderr, "parsing CA certificate failed\n");
+					goto end;
+				}
+				has_ca = TRUE;
+				creds->add_cert(creds, TRUE, cert);
+				continue;
+			case 'o':
+				online = TRUE;
 				continue;
 			case EOF:
 				break;
 			default:
+				creds->destroy(creds);
 				return command_usage("invalid --verify option");
 		}
 		break;
@@ -59,10 +80,11 @@ static int verify()
 	{
 		chunk_t chunk;
 
+		set_file_mode(stdin, CERT_ASN1_DER);
 		if (!chunk_from_fd(0, &chunk))
 		{
 			fprintf(stderr, "reading certificate failed: %s\n", strerror(errno));
-			return 1;
+			goto end;
 		}
 		cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
 								  BUILD_BLOB, chunk, BUILD_END);
@@ -71,60 +93,76 @@ static int verify()
 	if (!cert)
 	{
 		fprintf(stderr, "parsing certificate failed\n");
-		return 1;
-	}
-	if (cafile)
-	{
-		ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
-								BUILD_FROM_FILE, cafile, BUILD_END);
-		if (!ca)
-		{
-			fprintf(stderr, "parsing CA certificate failed\n");
-			return 1;
-		}
+		goto end;
 	}
-	else
-	{
-		ca = cert;
-	}
-	if (cert->issued_by(cert, ca, NULL))
+	creds->add_cert(creds, !has_ca, cert);
+
+	enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+									KEY_ANY, cert->get_subject(cert), online);
+	if (enumerator->enumerate(enumerator, &cert, &auth))
 	{
+		trusted = TRUE;
 		if (cert->get_validity(cert, NULL, NULL, NULL))
 		{
-			if (cafile)
-			{
-				if (ca->get_validity(ca, NULL, NULL, NULL))
-				{
-					printf("signature good, certificates valid\n");
-					good = TRUE;
-				}
-				else
-				{
-					printf("signature good, CA certificates not valid now\n");
-				}
-			}
-			else
-			{
-				printf("signature good, certificate valid\n");
-				good = TRUE;
-			}
+			printf("certificate trusted, lifetimes valid");
+			valid = TRUE;
 		}
 		else
 		{
-			printf("certificate not valid now\n");
+			printf("certificate trusted, but no valid lifetime");
 		}
+		if (online)
+		{
+			switch ((uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION))
+			{
+				case VALIDATION_GOOD:
+					printf(", certificate not revoked");
+					break;
+				case VALIDATION_SKIPPED:
+					printf(", no revocation information");
+					break;
+				case VALIDATION_STALE:
+					printf(", revocation information stale");
+					break;
+				case VALIDATION_FAILED:
+					printf(", revocation checking failed");
+					break;
+				case VALIDATION_ON_HOLD:
+					printf(", certificate revocation on hold");
+					revoked = TRUE;
+					break;
+				case VALIDATION_REVOKED:
+					printf(", certificate revoked");
+					revoked = TRUE;
+					break;
+			}
+		}
+		printf("\n");
 	}
-	else
+	enumerator->destroy(enumerator);
+
+	if (!trusted)
 	{
-		printf("signature invalid\n");
+		printf("certificate untrusted\n");
 	}
-	if (cafile)
+
+end:
+	lib->credmgr->remove_set(lib->credmgr, &creds->set);
+	creds->destroy(creds);
+
+	if (!trusted)
 	{
-		ca->destroy(ca);
+		return 1;
 	}
-	cert->destroy(cert);
-
-	return good ? 0 : 2;
+	if (!valid)
+	{
+		return 2;
+	}
+	if (revoked)
+	{
+		return 3;
+	}
+	return 0;
 }
 
 /**
@@ -139,7 +177,8 @@ static void __attribute__ ((constructor))reg()
 		{
 			{"help",	'h', 0, "show usage information"},
 			{"in",		'i', 1, "X.509 certificate to verify, default: stdin"},
-			{"cacert",	'c', 1, "CA certificate, default: verify self signed"},
+			{"cacert",	'c', 1, "CA certificate for trustchain verification"},
+			{"online",	'o', 0, "enable online CRL/OCSP revocation checking"},
 		}
 	});
 }
diff --git a/src/pki/man/Makefile.in b/src/pki/man/Makefile.in
index 5d901a8..4c0efd5 100644
--- a/src/pki/man/Makefile.in
+++ b/src/pki/man/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -218,6 +218,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -236,6 +237,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -263,6 +265,7 @@ 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@
@@ -354,6 +357,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/pki/man/pki---verify.1.in b/src/pki/man/pki---verify.1.in
index de34aca..dd0c0e9 100644
--- a/src/pki/man/pki---verify.1.in
+++ b/src/pki/man/pki---verify.1.in
@@ -10,6 +10,7 @@ pki \-\-verify \- Verify a certificate using a CA certificate
 .OP \-\-in file
 .OP \-\-cacert file
 .OP \-\-debug level
+.OP \-\-online
 .YS
 .
 .SY pki\ \-\-verify
@@ -44,13 +45,18 @@ Read command line options from \fIfile\fR.
 X.509 certificate to verify. If not given it is read from \fISTDIN\fR.
 .TP
 .BI "\-c, \-\-cacert " file
-CA certificate to use. If not given the certificate is assumed to be
-self-signed.
+CA certificate to use for trustchain verification. If not given the certificate
+is assumed to be self\-signed.
+.TP
+.BI "\-o, \-\-online
+Enable online CRL/OCSP revocation checking.
 .
 .SH "EXIT STATUS"
-The exit status is 0 if the certificate was verified successfully, and 2 if
-the verification failed.
+The exit status is 0 if the certificate was verified successfully, 1 if the
+certificate is untrusted, 2 if the certificate's lifetimes are invalid, and 3
+if the certificate was verified successfully but the online revocation check
+indicated that it has been revoked.
 .
 .SH "SEE ALSO"
 .
-.BR pki (1)
\ No newline at end of file
+.BR pki (1)
diff --git a/src/pki/pki.c b/src/pki/pki.c
index ae4ef1c..434287d 100644
--- a/src/pki/pki.c
+++ b/src/pki/pki.c
@@ -19,6 +19,7 @@
 
 #include <time.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include <utils/debug.h>
 #include <credentials/sets/callback_cred.h>
@@ -104,13 +105,12 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type)
 }
 
 /**
- * See header
+ * Convert a time string to struct tm using strptime format
  */
-bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
-						time_t *nb, time_t *na)
+static bool convert_time(char *str, char *format, struct tm *tm)
 {
-	struct tm tm;
-	time_t now;
+#ifdef HAVE_STRPTIME
+
 	char *end;
 
 	if (!format)
@@ -118,29 +118,84 @@ bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
 		format = "%d.%m.%y %T";
 	}
 
+	end = strptime(str, format, tm);
+	if (end == NULL || *end != '\0')
+	{
+		return FALSE;
+	}
+	return TRUE;
+
+#else /* !HAVE_STRPTIME */
+
+	if (format)
+	{
+		fprintf(stderr, "custom datetime string format not supported\n");
+		return FALSE;
+	}
+
+	if (sscanf(str, "%d.%d.%d %d:%d:%d",
+			   &tm->tm_mday, &tm->tm_mon, &tm->tm_year,
+			   &tm->tm_hour, &tm->tm_min, &tm->tm_sec) != 6)
+	{
+		return FALSE;
+	}
+	/* strptime() interprets two-digit years > 68 as 19xx, do the same here.
+	 * mktime() expects years based on 1900 */
+	if (tm->tm_year <= 68)
+	{
+		tm->tm_year += 100;
+	}
+	else if (tm->tm_year >= 1900)
+	{	/* looks like four digits? */
+		tm->tm_year -= 1900;
+	}
+	/* month is specified from 0-11 */
+	tm->tm_mon--;
+	/* automatically detect daylight saving time */
+	tm->tm_isdst = -1;
+	return TRUE;
+
+#endif /* !HAVE_STRPTIME */
+}
+
+/**
+ * See header
+ */
+bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
+						time_t *nb, time_t *na)
+{
+	struct tm tm;
+	time_t now;
+
 	now = time(NULL);
 
 	localtime_r(&now, &tm);
 	if (nbstr)
 	{
-		end = strptime(nbstr, format, &tm);
-		if (end == NULL || *end != '\0')
+		if (!convert_time(nbstr, format, &tm))
 		{
 			return FALSE;
 		}
 	}
 	*nb = mktime(&tm);
+	if (*nb == -1)
+	{
+		return FALSE;
+	}
 
 	localtime_r(&now, &tm);
 	if (nastr)
 	{
-		end = strptime(nastr, format, &tm);
-		if (end == NULL || *end != '\0')
+		if (!convert_time(nastr, format, &tm))
 		{
 			return FALSE;
 		}
 	}
 	*na = mktime(&tm);
+	if (*na == -1)
+	{
+		return FALSE;
+	}
 
 	if (!nbstr && nastr)
 	{
@@ -154,6 +209,33 @@ bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
 }
 
 /**
+ * Set output file mode appropriate for credential encoding form on Windows
+ */
+void set_file_mode(FILE *stream, cred_encoding_type_t enc)
+{
+#ifdef WIN32
+	int fd;
+
+	switch (enc)
+	{
+		case CERT_PEM:
+		case PRIVKEY_PEM:
+		case PUBKEY_PEM:
+			/* keep default text mode */
+			return;
+		default:
+			/* switch to binary mode */
+			break;
+	}
+	fd = fileno(stream);
+	if (fd != -1)
+	{
+		_setmode(fd, _O_BINARY);
+	}
+#endif
+}
+
+/**
  * Callback credential set pki uses
  */
 static callback_cred_t *cb_set;
@@ -165,7 +247,7 @@ static shared_key_t* cb(void *data, shared_key_type_t type,
 						identification_t *me, identification_t *other,
 						id_match_t *match_me, id_match_t *match_other)
 {
-	char buf[64], *label, *secret;
+	char buf[64], *label, *secret = NULL;
 
 	switch (type)
 	{
@@ -179,8 +261,10 @@ static shared_key_t* cb(void *data, shared_key_type_t type,
 			return NULL;
 	}
 	snprintf(buf, sizeof(buf), "%s: ", label);
+#ifdef HAVE_GETPASS
 	secret = getpass(buf);
-	if (secret)
+#endif
+	if (secret && strlen(secret))
 	{
 		if (match_me)
 		{
diff --git a/src/pki/pki.h b/src/pki/pki.h
index 616fac4..1f08277 100644
--- a/src/pki/pki.h
+++ b/src/pki/pki.h
@@ -50,4 +50,9 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type);
 bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
 						time_t *nb, time_t *na);
 
+/**
+ * Set output file mode appropriate for credential encoding form on Windows
+ */
+void set_file_mode(FILE *stream, cred_encoding_type_t enc);
+
 #endif /** PKI_H_ @}*/
diff --git a/src/pool/Makefile.in b/src/pool/Makefile.in
index e8caddc..54a1a84 100644
--- a/src/pool/Makefile.in
+++ b/src/pool/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ 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@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/pt-tls-client/Makefile.am b/src/pt-tls-client/Makefile.am
index 2ce1a10..8d1567e 100644
--- a/src/pt-tls-client/Makefile.am
+++ b/src/pt-tls-client/Makefile.am
@@ -11,7 +11,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtncif \
 	-I$(top_srcdir)/src/libtnccs \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
-	-DPLUGINS="\"pem openssl nonce tnc-tnccs tnc-imc tnccs-20\""
+	-DPLUGINS="\"x509 pem pkcs1 pubkey openssl nonce tnc-tnccs tnc-imc tnccs-20\""
 
 pt_tls_client_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
diff --git a/src/pt-tls-client/Makefile.in b/src/pt-tls-client/Makefile.in
index d9a8259..efbba98 100644
--- a/src/pt-tls-client/Makefile.in
+++ b/src/pt-tls-client/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -235,6 +235,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -253,6 +254,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -280,6 +282,7 @@ 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@
@@ -371,6 +374,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -389,7 +393,7 @@ AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/libtncif \
 	-I$(top_srcdir)/src/libtnccs \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
-	-DPLUGINS="\"pem openssl nonce tnc-tnccs tnc-imc tnccs-20\""
+	-DPLUGINS="\"x509 pem pkcs1 pubkey openssl nonce tnc-tnccs tnc-imc tnccs-20\""
 
 pt_tls_client_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
diff --git a/src/pt-tls-client/pt-tls-client.c b/src/pt-tls-client/pt-tls-client.c
index 90edb0c..8b41ae2 100644
--- a/src/pt-tls-client/pt-tls-client.c
+++ b/src/pt-tls-client/pt-tls-client.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2010-2013 Martin Willi, revosec AG
- * Copyright (C) 2013 Andreas Steffen, HSR Hochschule für Technik Rapperswil
+ * Copyright (C) 2013-2014 Andreas Steffen
+ * HSR Hochschule für 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
@@ -16,11 +17,13 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <getopt.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
+#ifdef HAVE_SYSLOG
+#include <syslog.h>
+#endif
 
 #include <pt_tls.h>
 #include <pt_tls_client.h>
@@ -35,12 +38,13 @@
 /**
  * Print usage information
  */
-static void usage(FILE *out, char *cmd)
+static void usage(FILE *out)
 {
-	fprintf(out, "usage:\n");
-	fprintf(out, "  %s --connect <address> [--port <port>] [--cert <file>]+\n", cmd);
-	fprintf(out, "               [--client <client-id>] [--secret <password>]\n");
-	fprintf(out, "	             [--optionsfrom <filename>]\n");
+	fprintf(out,
+		"Usage: pt-tls  --connect <hostname|address> [--port <port>]\n"
+		"              [--cert <file>]+ [--key <file>]\n"
+		"              [--client <client-id>] [--secret <password>]\n"
+		"              [--optionsfrom <filename>] [--quiet] [--debug <level>]\n");
 }
 
 /**
@@ -121,24 +125,74 @@ static bool load_key(char *filename)
 }
 
 /**
- * Debug level
+ * Logging and debug level
  */
-static level_t pt_tls_level = 1;
+static bool log_to_stderr = TRUE;
+#ifdef HAVE_SYSLOG
+static bool log_to_syslog = TRUE;
+#endif /* HAVE_SYSLOG */
+static level_t default_loglevel = 1;
 
 static void dbg_pt_tls(debug_t group, level_t level, char *fmt, ...)
 {
-	if (level <= pt_tls_level)
+	va_list args;
+
+	if (level <= default_loglevel)
 	{
-		va_list args;
+		if (log_to_stderr)
+		{
+			va_start(args, fmt);
+			vfprintf(stderr, fmt, args);
+			va_end(args);
+			fprintf(stderr, "\n");
+		}
+#ifdef HAVE_SYSLOG
+		if (log_to_syslog)
+		{
+			char buffer[8192];
+			char *current = buffer, *next;
+
+			/* write in memory buffer first */
+			va_start(args, fmt);
+			vsnprintf(buffer, sizeof(buffer), fmt, args);
+			va_end(args);
 
-		va_start(args, fmt);
-		vfprintf(stderr, fmt, args);
-		fprintf(stderr, "\n");
-		va_end(args);
+			/* do a syslog with every line */
+			while (current)
+			{
+				next = strchr(current, '\n');
+				if (next)
+				{
+					*(next++) = '\0';
+				}
+				syslog(LOG_INFO, "%s\n", current);
+				current = next;
+			}
+		}
+#endif /* HAVE_SYSLOG */
 	}
 }
 
 /**
+ * Initialize logging to stderr/syslog
+ */
+static void init_log(const char *program)
+{
+	dbg = dbg_pt_tls;
+
+	if (log_to_stderr)
+	{
+		setbuf(stderr, NULL);
+	}
+#ifdef HAVE_SYSLOG
+	if (log_to_syslog)
+	{
+		openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
+	}
+#endif /* HAVE_SYSLOG */
+}
+
+/**
  * Handles --optionsfrom arguments
  */
 options_t *options;
@@ -169,7 +223,7 @@ static void init()
 	library_init(NULL, "pt-tls-client");
 	libtnccs_init();
 
-	dbg = dbg_pt_tls;
+	init_log("pt-tls-client");
 	options = options_create();
 
 	lib->plugins->add_static_features(lib->plugins, "pt-tls-client", features,
@@ -204,6 +258,7 @@ int main(int argc, char *argv[])
 			{"port",		required_argument,		NULL,		'p' },
 			{"cert",		required_argument,		NULL,		'x' },
 			{"key",			required_argument,		NULL,		'k' },
+			{"quiet",		no_argument,			NULL,		'q' },
 			{"debug",		required_argument,		NULL,		'd' },
 			{"optionsfrom",	required_argument,		NULL,		'+' },
 			{0,0,0,0 }
@@ -212,56 +267,59 @@ int main(int argc, char *argv[])
 		{
 			case EOF:
 				break;
-			case 'h':
-				usage(stdout, argv[0]);
+			case 'h':			/* --help */
+				usage(stdout);
 				return 0;
-			case 'x':
+			case 'x':			/* --cert <file> */
 				if (!load_certificate(optarg))
 				{
 					return 1;
 				}
 				continue;
-			case 'k':
+			case 'k':			/* --key <file> */
 				if (!load_key(optarg))
 				{
 					return 1;
 				}
 				continue;
-			case 'c':
+			case 'c':			/* --connect <hostname|address> */
 				if (address)
 				{
-					usage(stderr, argv[0]);
+					usage(stderr);
 					return 1;
 				}
 				address = optarg;
 				continue;
-			case 'i':
+			case 'i':			/* --client <client-id> */
 				identity = optarg;
 				continue;
-			case 's':
+			case 's':			/* --secret <password> */
 				secret = optarg;
 				continue;
-			case 'p':
+			case 'p':			/* --port <port> */
 				port = atoi(optarg);
 				continue;
-			case 'd':
-				pt_tls_level = atoi(optarg);
+			case 'q':       	/* --quiet */
+				log_to_stderr = FALSE;
+				continue;
+			case 'd':			/* --debug <level> */
+				default_loglevel = atoi(optarg);
 				continue;
-			case '+':	/* --optionsfrom <filename> */
+			case '+':			/* --optionsfrom <filename> */
 				if (!options->from(options, optarg, &argc, &argv, optind))
 				{
 					return 1;
 				}
 				continue;
 			default:
-				usage(stderr, argv[0]);
+				usage(stderr);
 				return 1;
 		}
 		break;
 	}
 	if (!address)
 	{
-		usage(stderr, argv[0]);
+		usage(stderr);
 		return 1;
 	}
 	if (secret)
diff --git a/src/scepclient/Android.mk b/src/scepclient/Android.mk
new file mode 100644
index 0000000..bec3d77
--- /dev/null
+++ b/src/scepclient/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+scepclient_SOURCES := \
+scepclient.c scep.c scep.h
+
+LOCAL_SRC_FILES := $(filter %.c,$(scepclient_SOURCES))
+
+# build scepclient -------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+	$(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS) \
+	-DPLUGINS='"$(strongswan_SCEPCLIENT_PLUGINS)"'
+
+LOCAL_MODULE := scepclient
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan
+
+include $(BUILD_EXECUTABLE)
\ No newline at end of file
diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am
index c911be1..b3beb1b 100644
--- a/src/scepclient/Makefile.am
+++ b/src/scepclient/Makefile.am
@@ -14,3 +14,4 @@ scepclient_LDADD = \
 $(top_builddir)/src/libstrongswan/libstrongswan.la
 
 dist_man_MANS = scepclient.8
+EXTRA_DIST = Android.mk
diff --git a/src/scepclient/Makefile.in b/src/scepclient/Makefile.in
index 524e05b..27a6b82 100644
--- a/src/scepclient/Makefile.in
+++ b/src/scepclient/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -262,6 +262,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -280,6 +281,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -307,6 +309,7 @@ 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@
@@ -398,6 +401,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -421,6 +425,7 @@ scepclient_LDADD = \
 $(top_builddir)/src/libstrongswan/libstrongswan.la
 
 dist_man_MANS = scepclient.8
+EXTRA_DIST = Android.mk
 all: all-am
 
 .SUFFIXES:
diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c
index d7abcb4..853490f 100644
--- a/src/scepclient/scepclient.c
+++ b/src/scepclient/scepclient.c
@@ -896,7 +896,7 @@ int main(int argc, char **argv)
 					}
 					hash = hasher_algorithm_from_integrity(token->algorithm,
 														   NULL);
-					if (hash == OID_UNKNOWN)
+					if (hash == (hash_algorithm_t)OID_UNKNOWN)
 					{
 						usage("invalid algorithm specified");
 					}
diff --git a/src/starter/Android.mk b/src/starter/Android.mk
index c2260be..c37fc1a 100644
--- a/src/starter/Android.mk
+++ b/src/starter/Android.mk
@@ -3,11 +3,11 @@ include $(CLEAR_VARS)
 
 # copy-n-paste from Makefile.am (update for LEX/YACC)
 starter_SOURCES := \
-parser.c lexer.c ipsec-parser.h netkey.c args.h netkey.h \
-starterstroke.c confread.c \
-starterstroke.h confread.h args.c \
-keywords.c files.h keywords.h cmp.c starter.c cmp.h invokecharon.c \
-invokecharon.h klips.c klips.h
+starter.c files.h \
+parser/parser.c parser/lexer.c parser/conf_parser.c parser/conf_parser.h \
+args.c args.h confread.c confread.h keywords.c keywords.h cmp.c cmp.h \
+invokecharon.c invokecharon.h starterstroke.c starterstroke.h \
+netkey.c netkey.h klips.c klips.h
 
 LOCAL_SRC_FILES := $(filter %.c,$(starter_SOURCES))
 
@@ -16,9 +16,11 @@ LOCAL_SRC_FILES := $(filter %.c,$(starter_SOURCES))
 LOCAL_C_INCLUDES += \
 	$(strongswan_PATH)/src/libhydra \
 	$(strongswan_PATH)/src/libstrongswan \
+	$(strongswan_PATH)/src/starter \
 	$(strongswan_PATH)/src/stroke
 
 LOCAL_CFLAGS := $(strongswan_CFLAGS) -DSTART_CHARON \
+	-DIPSEC_SCRIPT='"ipsec"' \
 	-DPLUGINS='"$(strongswan_STARTER_PLUGINS)"'
 
 LOCAL_MODULE := starter
diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am
index 48110dd..f0a2be8 100644
--- a/src/starter/Makefile.am
+++ b/src/starter/Makefile.am
@@ -1,15 +1,22 @@
+SUBDIRS = . tests
+
 ipsec_PROGRAMS = starter
 starter_SOURCES = \
-parser.y lexer.l ipsec-parser.h netkey.c args.h netkey.h \
-starterstroke.c confread.c \
-starterstroke.h confread.h args.c \
-keywords.c files.h keywords.h cmp.c starter.c cmp.h invokecharon.c \
-invokecharon.h klips.c klips.h
+starter.c files.h \
+args.c args.h confread.c confread.h keywords.c keywords.h cmp.c cmp.h \
+invokecharon.c invokecharon.h starterstroke.c starterstroke.h \
+netkey.c netkey.h klips.c klips.h
+
+# parser is also used by tests
+noinst_LTLIBRARIES = libstarter.la
+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/stroke \
 	-DIPSEC_DIR=\"${ipsecdir}\" \
 	-DIPSEC_CONFDIR=\"${sysconfdir}\" \
@@ -23,10 +30,15 @@ AM_CPPFLAGS = \
 
 AM_YFLAGS = -v -d
 
-starter_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libhydra/libhydra.la $(SOCKLIB) $(PTHREADLIB)
+starter_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libhydra/libhydra.la \
+	libstarter.la \
+	$(SOCKLIB) $(PTHREADLIB)
+
 EXTRA_DIST = keywords.txt ipsec.conf Android.mk
 MAINTAINERCLEANFILES = keywords.c
-BUILT_SOURCES = parser.h
+BUILT_SOURCES = keywords.c parser/parser.h
 
 if USE_CHARON
   AM_CPPFLAGS += -DSTART_CHARON
@@ -36,7 +48,7 @@ if USE_LOAD_WARNING
   AM_CPPFLAGS += -DLOAD_WARNING
 endif
 
-if USE_TOOLS
+if USE_SCEPCLIENT
   AM_CPPFLAGS += -DGENERATE_SELFCERT
 endif
 
diff --git a/src/starter/Makefile.in b/src/starter/Makefile.in
index 3f3200d..8beb47c 100644
--- a/src/starter/Makefile.in
+++ b/src/starter/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -14,6 +14,7 @@
 
 @SET_MAKE@
 
+
 VPATH = @srcdir@
 am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
 am__make_running_with_option = \
@@ -81,11 +82,11 @@ host_triplet = @host@
 ipsec_PROGRAMS = starter$(EXEEXT)
 @USE_CHARON_TRUE at am__append_1 = -DSTART_CHARON
 @USE_LOAD_WARNING_TRUE at am__append_2 = -DLOAD_WARNING
- at USE_TOOLS_TRUE@am__append_3 = -DGENERATE_SELFCERT
+ at USE_SCEPCLIENT_TRUE@am__append_3 = -DGENERATE_SELFCERT
 subdir = src/starter
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am parser.h \
-	parser.c lexer.c $(top_srcdir)/depcomp $(top_srcdir)/ylwrap \
-	README
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	parser/parser.h parser/parser.c parser/lexer.c \
+	$(top_srcdir)/depcomp $(top_srcdir)/ylwrap
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
 	$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -103,22 +104,28 @@ mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libstarter_la_LIBADD =
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libstarter_la_OBJECTS = parser/parser.lo parser/lexer.lo \
+	parser/conf_parser.lo
+libstarter_la_OBJECTS = $(am_libstarter_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__installdirs = "$(DESTDIR)$(ipsecdir)"
 PROGRAMS = $(ipsec_PROGRAMS)
-am_starter_OBJECTS = parser.$(OBJEXT) lexer.$(OBJEXT) netkey.$(OBJEXT) \
-	starterstroke.$(OBJEXT) confread.$(OBJEXT) args.$(OBJEXT) \
-	keywords.$(OBJEXT) cmp.$(OBJEXT) starter.$(OBJEXT) \
-	invokecharon.$(OBJEXT) klips.$(OBJEXT)
+am_starter_OBJECTS = starter.$(OBJEXT) args.$(OBJEXT) \
+	confread.$(OBJEXT) keywords.$(OBJEXT) cmp.$(OBJEXT) \
+	invokecharon.$(OBJEXT) starterstroke.$(OBJEXT) \
+	netkey.$(OBJEXT) klips.$(OBJEXT)
 starter_OBJECTS = $(am_starter_OBJECTS)
 am__DEPENDENCIES_1 =
 starter_DEPENDENCIES =  \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
-	$(top_builddir)/src/libhydra/libhydra.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
-am__v_lt_1 = 
+	$(top_builddir)/src/libhydra/libhydra.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@)
 am__v_P_0 = false
@@ -170,13 +177,29 @@ AM_V_YACC = $(am__v_YACC_ at AM_V@)
 am__v_YACC_ = $(am__v_YACC_ at AM_DEFAULT_V@)
 am__v_YACC_0 = @echo "  YACC    " $@;
 am__v_YACC_1 = 
-SOURCES = $(starter_SOURCES)
-DIST_SOURCES = $(starter_SOURCES)
+SOURCES = $(libstarter_la_SOURCES) $(starter_SOURCES)
+DIST_SOURCES = $(libstarter_la_SOURCES) $(starter_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
@@ -196,7 +219,33 @@ am__define_uniq_tagged_files = \
   done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
 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@
@@ -259,6 +308,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -277,6 +327,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -304,6 +355,7 @@ 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@
@@ -395,6 +447,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
@@ -405,29 +458,41 @@ top_srcdir = @top_srcdir@
 urandom_device = @urandom_device@
 xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
+SUBDIRS = . tests
 starter_SOURCES = \
-parser.y lexer.l ipsec-parser.h netkey.c args.h netkey.h \
-starterstroke.c confread.c \
-starterstroke.h confread.h args.c \
-keywords.c files.h keywords.h cmp.c starter.c cmp.h invokecharon.c \
-invokecharon.h klips.c klips.h
+starter.c files.h \
+args.c args.h confread.c confread.h keywords.c keywords.h cmp.c cmp.h \
+invokecharon.c invokecharon.h starterstroke.c starterstroke.h \
+netkey.c netkey.h klips.c klips.h
+
+
+# parser is also used by tests
+noinst_LTLIBRARIES = libstarter.la
+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/stroke \
-	-DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_CONFDIR=\"${sysconfdir}\" \
-	-DIPSEC_PIDDIR=\"${piddir}\" -DIPSEC_EAPDIR=\"${eapdir}\" \
+	-I$(top_srcdir)/src/libhydra -I$(top_srcdir)/src/starter \
+	-I$(top_srcdir)/src/stroke -DIPSEC_DIR=\"${ipsecdir}\" \
+	-DIPSEC_CONFDIR=\"${sysconfdir}\" -DIPSEC_PIDDIR=\"${piddir}\" \
+	-DIPSEC_EAPDIR=\"${eapdir}\" \
 	-DIPSEC_SCRIPT=\"${ipsec_script}\" \
 	-DDEV_RANDOM=\"${random_device}\" \
 	-DDEV_URANDOM=\"${urandom_device}\" \
 	-DPLUGINS=\""${starter_plugins}\"" -DDEBUG $(am__append_1) \
 	$(am__append_2) $(am__append_3)
 AM_YFLAGS = -v -d
-starter_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la $(top_builddir)/src/libhydra/libhydra.la $(SOCKLIB) $(PTHREADLIB)
+starter_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libhydra/libhydra.la \
+	libstarter.la \
+	$(SOCKLIB) $(PTHREADLIB)
+
 EXTRA_DIST = keywords.txt ipsec.conf Android.mk
 MAINTAINERCLEANFILES = keywords.c
-BUILT_SOURCES = parser.h
+BUILT_SOURCES = keywords.c parser/parser.h
 all: $(BUILT_SOURCES)
-	$(MAKE) $(AM_MAKEFLAGS) all-am
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
 
 .SUFFIXES:
 .SUFFIXES: .c .l .lo .o .obj .y
@@ -461,6 +526,35 @@ $(top_srcdir)/configure:  $(am__configure_deps)
 $(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}; \
+	}
+parser/parser.h: parser/parser.c
+	@if test ! -f $@; then rm -f parser/parser.c; else :; fi
+	@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) parser/parser.c; else :; fi
+parser/$(am__dirstamp):
+	@$(MKDIR_P) parser
+	@: > parser/$(am__dirstamp)
+parser/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) parser/$(DEPDIR)
+	@: > parser/$(DEPDIR)/$(am__dirstamp)
+parser/parser.lo: parser/$(am__dirstamp) \
+	parser/$(DEPDIR)/$(am__dirstamp)
+parser/lexer.lo: parser/$(am__dirstamp) \
+	parser/$(DEPDIR)/$(am__dirstamp)
+parser/conf_parser.lo: parser/$(am__dirstamp) \
+	parser/$(DEPDIR)/$(am__dirstamp)
+
+libstarter.la: $(libstarter_la_OBJECTS) $(libstarter_la_DEPENDENCIES) $(EXTRA_libstarter_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(LINK)  $(libstarter_la_OBJECTS) $(libstarter_la_LIBADD) $(LIBS)
 install-ipsecPROGRAMS: $(ipsec_PROGRAMS)
 	@$(NORMAL_INSTALL)
 	@list='$(ipsec_PROGRAMS)'; test -n "$(ipsecdir)" || list=; \
@@ -510,9 +604,6 @@ clean-ipsecPROGRAMS:
 	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
 	echo " rm -f" $$list; \
 	rm -f $$list
-parser.h: parser.c
-	@if test ! -f $@; then rm -f parser.c; else :; fi
-	@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) parser.c; else :; fi
 
 starter$(EXEEXT): $(starter_OBJECTS) $(starter_DEPENDENCIES) $(EXTRA_starter_DEPENDENCIES) 
 	@rm -f starter$(EXEEXT)
@@ -520,6 +611,8 @@ starter$(EXEEXT): $(starter_OBJECTS) $(starter_DEPENDENCIES) $(EXTRA_starter_DEP
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
+	-rm -f parser/*.$(OBJEXT)
+	-rm -f parser/*.lo
 
 distclean-compile:
 	-rm -f *.tab.c
@@ -530,11 +623,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/invokecharon.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/keywords.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/klips.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/lexer.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/netkey.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/parser.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/starter.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/starterstroke.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at parser/$(DEPDIR)/conf_parser.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at parser/$(DEPDIR)/lexer.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at parser/$(DEPDIR)/parser.Plo at am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -571,15 +665,63 @@ mostlyclean-libtool:
 
 clean-libtool:
 	-rm -rf .libs _libs
+	-rm -rf parser/.libs parser/_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-am
+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 \
@@ -592,7 +734,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
 	      $$unique; \
 	  fi; \
 	fi
-ctags: ctags-am
+ctags: ctags-recursive
 
 CTAGS: ctags
 ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
@@ -605,7 +747,7 @@ GTAGS:
 	here=`$(am__cd) $(top_builddir) && pwd` \
 	  && $(am__cd) $(top_srcdir) \
 	  && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
+cscopelist: cscopelist-recursive
 
 cscopelist-am: $(am__tagged_files)
 	list='$(am__tagged_files)'; \
@@ -654,24 +796,50 @@ distdir: $(DISTFILES)
 	    || 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: $(BUILT_SOURCES)
-	$(MAKE) $(AM_MAKEFLAGS) check-am
-all-am: Makefile $(PROGRAMS)
-installdirs:
+	$(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
 	for dir in "$(DESTDIR)$(ipsecdir)"; do \
 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
 	done
 install: $(BUILT_SOURCES)
-	$(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+	$(MAKE) $(AM_MAKEFLAGS) 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-am
+installcheck: installcheck-recursive
 install-strip:
 	if test -z '$(STRIP)'; then \
 	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
@@ -689,99 +857,102 @@ 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 parser/$(DEPDIR)/$(am__dirstamp)
+	-rm -f parser/$(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."
-	-rm -f lexer.c
-	-rm -f parser.c
-	-rm -f parser.h
+	-rm -f parser/lexer.c
+	-rm -f parser/parser.c
+	-rm -f parser/parser.h
 	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
 	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-clean: clean-am
+clean: clean-recursive
 
 clean-am: clean-generic clean-ipsecPROGRAMS clean-libtool \
-	mostlyclean-am
+	clean-noinstLTLIBRARIES mostlyclean-am
 
-distclean: distclean-am
-	-rm -rf ./$(DEPDIR)
+distclean: distclean-recursive
+	-rm -rf ./$(DEPDIR) parser/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-tags
 
-dvi: dvi-am
+dvi: dvi-recursive
 
 dvi-am:
 
-html: html-am
+html: html-recursive
 
 html-am:
 
-info: info-am
+info: info-recursive
 
 info-am:
 
 install-data-am: install-ipsecPROGRAMS
 
-install-dvi: install-dvi-am
+install-dvi: install-dvi-recursive
 
 install-dvi-am:
 
 install-exec-am: install-exec-local
 
-install-html: install-html-am
+install-html: install-html-recursive
 
 install-html-am:
 
-install-info: install-info-am
+install-info: install-info-recursive
 
 install-info-am:
 
 install-man:
 
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
 
 install-pdf-am:
 
-install-ps: install-ps-am
+install-ps: install-ps-recursive
 
 install-ps-am:
 
 installcheck-am:
 
-maintainer-clean: maintainer-clean-am
-	-rm -rf ./$(DEPDIR)
+maintainer-clean: maintainer-clean-recursive
+	-rm -rf ./$(DEPDIR) parser/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
 
 mostlyclean-am: mostlyclean-compile mostlyclean-generic \
 	mostlyclean-libtool
 
-pdf: pdf-am
+pdf: pdf-recursive
 
 pdf-am:
 
-ps: ps-am
+ps: ps-recursive
 
 ps-am:
 
 uninstall-am: uninstall-ipsecPROGRAMS
 
-.MAKE: all check install install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-	clean-ipsecPROGRAMS 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-exec-local install-html \
-	install-html-am install-info install-info-am \
+.MAKE: $(am__recursive_targets) all check install install-am \
+	install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+	check-am clean clean-generic clean-ipsecPROGRAMS clean-libtool \
+	clean-noinstLTLIBRARIES 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-exec-local \
+	install-html install-html-am install-info install-info-am \
 	install-ipsecPROGRAMS install-man install-pdf install-pdf-am \
 	install-ps install-ps-am install-strip installcheck \
-	installcheck-am installdirs maintainer-clean \
+	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-ipsecPROGRAMS
diff --git a/src/starter/README b/src/starter/README
deleted file mode 100644
index 4aff649..0000000
--- a/src/starter/README
+++ /dev/null
@@ -1,101 +0,0 @@
-
-IPsec Starter -- Version 0.2        [Contributed by Arkoon Network Security]
-============================        [                http://www.arkoon.net/]
-
-IPsec Starter is aimed to replace all the scripts which are used to
-start and stop strongSwan and to do that in a quicker and a smarter way.
-
-IPsec Starter can also reload the configuration file (kill --HUP or periodicaly)
-and apply the changes.
-
-Usage:
-  starter [--debug] [--auto_update <x seconds>]
-    --debug:       enable debugging output
-    --no_fork:     all msg (including pluto) are sent to the console
-    --auto_update: reload the config file (like kill -HUP) every x seconds
-                   and determine any configuration changes
-
-FEATURES
---------
-
-o Load modules of the native Linux 2.6 IPsec stack
-
-o Launch and monitor pluto
-
-o Add, initiate, route and del connections
-
-o Attach and detach interfaces according to config file
-
-o kill -HUP can be used to reload the config file. New connections will be
-  added, old ones will be removed and modified ones will be reloaded.
-  Interfaces/Klips/Pluto will be reloaded if necessary.
-
-o Full support of the %defaultroute wildcard parameter.
-
-o save own pid in /var/run/starter
-
-o Upon reloading, dynamic DNS addr will be resolved and reloaded. Use
-  --auto_update to periodicaly check dynamic DNS changes.
-
-o kill -USR1 can be used to reload all connections (delete then add and
-  route/initiate)
-
-o /var/run/dynip/xxxx can be used to use a virtual interface name in
-  ipsec.conf. By example, when adsl can be ppp0, ppp1, ... :
-    ipsec.conf:             interfaces="ipsec0=adsl"
-  And use /etc/ppp/ip-up to create /var/run/dynip/adsl
-    /var/run/dynip/adsl:    IP_PHYS=ppp0
-
-o %auto can be used to automaticaly name the connections
-
-o kill -TERM can be used to stop FS. pluto will be stopped.
-
-o Can be used to start strongSwan and load lots of connections in a few
-  seconds.
-
-TODO
-----
-
-o handle wildcards in include lines -- use glob() fct
-    ex: include /etc/ipsec.*.conf
-
-o handle duplicates keywords and sections
-
-o 'also' keyword not supported
-
-o manually keyed connections
-
-o IPv6
-
-o Documentation
-
-
-CHANGES
--------
-
-o Version 0.1 -- 2002.01.14 -- First public release
-
-o Version 0.2 -- 2002.09.04 -- Various enhancements
-                               FreeS/WAN 1.98b, x509 0.9.14, algo 0.8.0
-
-o Version 0.2d -- 2004.01.13 -- Adaptions for Openswan 1.0.0
-                                by Stephan Scholz <sscholz at astaro.com>
-
-o Version 0.2e -- 2004.10.14 -- Added support for change of interface address
-                                by Stephan Scholz <sscholz at astaro.com>
-
-o Version 0.2s -- 2005-12-02 -- Ported to strongSwan
-                                by Stephan Scholz <sscholz at astaro.com>
-
-o Version 0.2x -- 2006-01-02 -- Added missing strongSwan keywords
-				Full support of the native Linux 2.6 IPsec stack
-				Full support of %defaultroute
-				Improved parsing of keywords using perfect hash
-				function generated by gperf.
-                                by Andreas Steffen <andreas.steffen at hsr.ch>
-
-THANKS
-------
-
-o Nathan Angelacos - include fix
-
diff --git a/src/starter/args.c b/src/starter/args.c
index f5a617e..0874cc7 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -1,6 +1,7 @@
-/* automatic handling of confread struct arguments
+/*
+ * Copyright (C) 2014 Tobias Brunner
  * Copyright (C) 2006 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+ * 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
@@ -20,7 +21,6 @@
 #include <library.h>
 #include <utils/debug.h>
 
-#include "keywords.h"
 #include "confread.h"
 #include "args.h"
 
@@ -36,7 +36,6 @@ typedef enum {
 	ARG_UBIN,
 	ARG_PCNT,
 	ARG_STR,
-	ARG_LST,
 	ARG_MISC
 } arg_t;
 
@@ -173,6 +172,7 @@ static const token_info_t token_info[] =
 	{ ARG_STR,  offsetof(starter_conn_t, me_mediated_by), NULL                     },
 	{ ARG_STR,  offsetof(starter_conn_t, me_peerid), NULL                          },
 	{ ARG_UINT, offsetof(starter_conn_t, reqid), NULL                              },
+	{ ARG_UINT, offsetof(starter_conn_t, replay_window), NULL                      },
 	{ ARG_MISC, 0, NULL  /* KW_MARK */                                             },
 	{ ARG_MISC, 0, NULL  /* KW_MARK_IN */                                          },
 	{ ARG_MISC, 0, NULL  /* KW_MARK_OUT */                                         },
@@ -218,123 +218,48 @@ static const token_info_t token_info[] =
 	{ ARG_MISC, 0, NULL  /* KW_END_DEPRECATED */                                   },
 };
 
-static void free_list(char **list)
-{
-	char **s;
-
-	for (s = list; *s; s++)
-	{
-		free(*s);
-	}
-	free(list);
-}
-
-char** new_list(char *value)
-{
-	char *val, *b, *e, *end, **ret;
-	int count;
-
-	val = strdupnull(value);
-	if (!val)
-	{
-		return NULL;
-	}
-	end = val + strlen(val);
-	for (b = val, count = 0; b < end;)
-	{
-		for (e = b; ((*e != ' ') && (*e != '\0')); e++);
-		*e = '\0';
-		if (e != b)
-		{
-			count++;
-		}
-		b = e + 1;
-	}
-	if (count == 0)
-	{
-		free(val);
-		return NULL;
-	}
-	ret = (char **)malloc((count+1) * sizeof(char *));
-
-	for (b = val, count = 0; b < end; )
-	{
-		for (e = b; (*e != '\0'); e++);
-		if (e != b)
-		{
-			ret[count++] = strdupnull(b);
-		}
-		b = e + 1;
-	}
-	ret[count] = NULL;
-	free(val);
-	return ret;
-}
-
-
 /*
  * assigns an argument value to a struct field
  */
-bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
-				bool *assigned)
+bool assign_arg(kw_token_t token, kw_token_t first, char *key, char *value,
+				void *base, bool *assigned)
 {
-	char *p = base + token_info[token].offset;
+	char *p = (char*)base + token_info[token].offset;
 	const char **list = token_info[token].list;
-
 	int index = -1;  /* used for enumeration arguments */
 
-	seen_t *seen = (seen_t*)base; /* seen flags are at the top of the struct */
-
 	*assigned = FALSE;
 
-	DBG3(DBG_APP, "  %s=%s", kw->entry->name, kw->value);
-
-	if (*seen & SEEN_KW(token, first))
-	{
-		DBG1(DBG_APP, "# duplicate '%s' option", kw->entry->name);
-		return FALSE;
-	}
-
-	if (token == KW_ESP || token == KW_AH)
-	{
-		if (*seen & (SEEN_KW(KW_ESP, first) | SEEN_KW(KW_AH, first)))
-		{
-			DBG1(DBG_APP, "# can't have both 'ah' and 'esp' options");
-			return FALSE;
-		}
-	}
-
-	/* set flag that this argument has been seen */
-	*seen |= SEEN_KW(token, first);
+	DBG3(DBG_APP, "  %s=%s", key, value);
 
 	/* is there a keyword list? */
-	if (list != NULL && token_info[token].type != ARG_LST)
+	if (list != NULL)
 	{
 		bool match = FALSE;
 
 		while (*list != NULL && !match)
 		{
 			index++;
-			match = streq(kw->value, *list++);
+			match = streq(value, *list++);
 		}
 		if (!match)
 		{
-			DBG1(DBG_APP, "# bad value: %s=%s", kw->entry->name, kw->value);
+			DBG1(DBG_APP, "# bad value: %s=%s", key, value);
 			return FALSE;
 		}
 	}
 
 	switch (token_info[token].type)
 	{
-	case ARG_NONE:
-		DBG1(DBG_APP, "# option '%s' not supported yet", kw->entry->name);
-		return FALSE;
-	case ARG_ENUM:
+		case ARG_NONE:
+			DBG1(DBG_APP, "# option '%s' not supported yet", key);
+			return FALSE;
+		case ARG_ENUM:
 		{
 			if (index < 0)
 			{
 				DBG1(DBG_APP, "# bad enumeration value: %s=%s (%d)",
-					 kw->entry->name, kw->value, index);
+					 key, value, index);
 				return FALSE;
 			}
 
@@ -344,93 +269,86 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
 				*b = (index > 0);
 			}
 			else
-			{
+			{	/* FIXME: this is not entirely correct as the args are enums */
 				int *i = (int *)p;
 				*i = index;
 			}
+			break;
 		}
-		break;
-
-	case ARG_UINT:
+		case ARG_UINT:
 		{
 			char *endptr;
 			u_int *u = (u_int *)p;
 
-			*u = strtoul(kw->value, &endptr, 10);
+			*u = strtoul(value, &endptr, 10);
 
 			if (*endptr != '\0')
 			{
-				DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
-					 kw->value);
+				DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
 				return FALSE;
 			}
+			break;
 		}
-		break;
-	case ARG_ULNG:
-	case ARG_PCNT:
+		case ARG_ULNG:
+		case ARG_PCNT:
 		{
 			char *endptr;
 			unsigned long *l = (unsigned long *)p;
 
-			*l = strtoul(kw->value, &endptr, 10);
+			*l = strtoul(value, &endptr, 10);
 
 			if (token_info[token].type == ARG_ULNG)
 			{
 				if (*endptr != '\0')
 				{
-					DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
-						 kw->value);
+					DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
 					return FALSE;
 				}
 			}
 			else
 			{
-				if ((*endptr != '%') || (endptr[1] != '\0') || endptr == kw->value)
+				if ((*endptr != '%') || (endptr[1] != '\0') || endptr == value)
 				{
-					DBG1(DBG_APP, "# bad percent value: %s=%s", kw->entry->name,
-						 kw->value);
+					DBG1(DBG_APP, "# bad percent value: %s=%s", key, value);
 					return FALSE;
 				}
 			}
-
+			break;
 		}
-		break;
-	case ARG_ULLI:
+		case ARG_ULLI:
 		{
 			char *endptr;
 			unsigned long long *ll = (unsigned long long *)p;
 
-			*ll = strtoull(kw->value, &endptr, 10);
+			*ll = strtoull(value, &endptr, 10);
 
 			if (*endptr != '\0')
 			{
-				DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
-					 kw->value);
+				DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
 				return FALSE;
 			}
+			break;
 		}
-		break;
-	case ARG_UBIN:
+		case ARG_UBIN:
 		{
 			char *endptr;
 			u_int *u = (u_int *)p;
 
-			*u = strtoul(kw->value, &endptr, 2);
+			*u = strtoul(value, &endptr, 2);
 
 			if (*endptr != '\0')
 			{
-				DBG1(DBG_APP, "# bad binary value: %s=%s", kw->entry->name,
-					 kw->value);
+				DBG1(DBG_APP, "# bad binary value: %s=%s", key, value);
 				return FALSE;
 			}
+			break;
 		}
-		break;
-	case ARG_TIME:
+		case ARG_TIME:
 		{
 			char *endptr;
 			time_t *t = (time_t *)p;
 
-			*t = strtoul(kw->value, &endptr, 10);
+			*t = strtoul(value, &endptr, 10);
 
 			/* time in seconds? */
 			if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0'))
@@ -455,60 +373,21 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
 					break;
 				}
 			}
-			DBG1(DBG_APP, "# bad duration value: %s=%s", kw->entry->name,
-				 kw->value);
+			DBG1(DBG_APP, "# bad duration value: %s=%s", key, value);
 			return FALSE;
 		}
-	case ARG_STR:
+		case ARG_STR:
 		{
 			char **cp = (char **)p;
 
 			/* free any existing string */
 			free(*cp);
-
 			/* assign the new string */
-			*cp = strdupnull(kw->value);
-		}
-		break;
-	case ARG_LST:
-		{
-			char ***listp = (char ***)p;
-
-			/* free any existing list */
-			if (*listp != NULL)
-			{
-				free_list(*listp);
-			}
-			/* create a new list and assign values */
-			*listp = new_list(kw->value);
-
-			/* is there a keyword list? */
-			if (list != NULL)
-			{
-				char ** lst;
-
-				for (lst = *listp; lst && *lst; lst++)
-				{
-					bool match = FALSE;
-
-					list = token_info[token].list;
-
-					while (*list != NULL && !match)
-					{
-						match = streq(*lst, *list++);
-					}
-					if (!match)
-					{
-						DBG1(DBG_APP, "# bad value: %s=%s",
-							 kw->entry->name, *lst);
-						return FALSE;
-					}
-				}
-			}
+			*cp = strdupnull(value);
+			break;
 		}
-		/* fall through */
-	default:
-		return TRUE;
+		default:
+			return TRUE;
 	}
 
 	*assigned = TRUE;
@@ -518,124 +397,69 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base,
 /*
  *  frees all dynamically allocated arguments in a struct
  */
-void free_args(kw_token_t first, kw_token_t last, char *base)
+void free_args(kw_token_t first, kw_token_t last, void *base)
 {
 	kw_token_t token;
 
 	for (token = first; token <= last; token++)
 	{
-		char *p = base + token_info[token].offset;
+		char *p = (char*)base + token_info[token].offset;
 
 		switch (token_info[token].type)
 		{
-		case ARG_STR:
+			case ARG_STR:
 			{
 				char **cp = (char **)p;
 
 				free(*cp);
 				*cp = NULL;
+				break;
 			}
-			break;
-		case ARG_LST:
-			{
-				char ***listp = (char ***)p;
-
-				if (*listp != NULL)
-				{
-					free_list(*listp);
-					*listp = NULL;
-				 }
-			}
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-/*
- *  clone all dynamically allocated arguments in a struct
- */
-void clone_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
-{
-	kw_token_t token;
-
-	for (token = first; token <= last; token++)
-	{
-		if (token_info[token].type == ARG_STR)
-		{
-			char **cp1 = (char **)(base1 + token_info[token].offset);
-			char **cp2 = (char **)(base2 + token_info[token].offset);
-
-			*cp1 = strdupnull(*cp2);
-		}
-	}
-}
-
-static bool cmp_list(char **list1, char **list2)
-{
-	if ((list1 == NULL) && (list2 == NULL))
-	{
-		return TRUE;
-	}
-	if ((list1 == NULL) || (list2 == NULL))
-	{
-		return FALSE;
-	}
-
-	for ( ; *list1 && *list2; list1++, list2++)
-	{
-		if (strcmp(*list1,*list2) != 0)
-		{
-			return FALSE;
+			default:
+				break;
 		}
 	}
-
-	if ((*list1 != NULL) || (*list2 != NULL))
-	{
-		return FALSE;
-	}
-
-	return TRUE;
 }
 
 /*
  *  compare all arguments in a struct
  */
-bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
+bool cmp_args(kw_token_t first, kw_token_t last, void *base1, void *base2)
 {
 	kw_token_t token;
 
 	for (token = first; token <= last; token++)
 	{
-		char *p1 = base1 + token_info[token].offset;
-		char *p2 = base2 + token_info[token].offset;
+		char *p1 = (char*)base1 + token_info[token].offset;
+		char *p2 = (char*)base2 + token_info[token].offset;
 
 		switch (token_info[token].type)
 		{
-		case ARG_ENUM:
-			if (token_info[token].list == LST_bool)
+			case ARG_ENUM:
 			{
-				bool *b1 = (bool *)p1;
-				bool *b2 = (bool *)p2;
-
-				if (*b1 != *b2)
+				if (token_info[token].list == LST_bool)
 				{
-					return FALSE;
-				}
-			}
-			else
-			{
-				int *i1 = (int *)p1;
-				int *i2 = (int *)p2;
+					bool *b1 = (bool *)p1;
+					bool *b2 = (bool *)p2;
 
-				if (*i1 != *i2)
+					if (*b1 != *b2)
+					{
+						return FALSE;
+					}
+				}
+				else
 				{
-					return FALSE;
+					int *i1 = (int *)p1;
+					int *i2 = (int *)p2;
+
+					if (*i1 != *i2)
+					{
+						return FALSE;
+					}
 				}
+				break;
 			}
-			break;
-		case ARG_UINT:
+			case ARG_UINT:
 			{
 				u_int *u1 = (u_int *)p1;
 				u_int *u2 = (u_int *)p2;
@@ -644,10 +468,10 @@ bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
 				{
 					return FALSE;
 				}
+				break;
 			}
-			break;
-		case ARG_ULNG:
-		case ARG_PCNT:
+			case ARG_ULNG:
+			case ARG_PCNT:
 			{
 				unsigned long *l1 = (unsigned long *)p1;
 				unsigned long *l2 = (unsigned long *)p2;
@@ -656,9 +480,9 @@ bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
 				{
 					return FALSE;
 				}
+				break;
 			}
-			break;
-		case ARG_ULLI:
+			case ARG_ULLI:
 			{
 				unsigned long long *ll1 = (unsigned long long *)p1;
 				unsigned long long *ll2 = (unsigned long long *)p2;
@@ -667,9 +491,9 @@ bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
 				{
 					return FALSE;
 				}
+				break;
 			}
-			break;
-		case ARG_TIME:
+			case ARG_TIME:
 			{
 				time_t *t1 = (time_t *)p1;
 				time_t *t2 = (time_t *)p2;
@@ -678,9 +502,9 @@ bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
 				{
 					return FALSE;
 				}
+				break;
 			}
-			break;
-		case ARG_STR:
+			case ARG_STR:
 			{
 				char **cp1 = (char **)p1;
 				char **cp2 = (char **)p2;
@@ -693,21 +517,10 @@ bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2)
 				{
 					return FALSE;
 				}
+				break;
 			}
-			break;
-		case ARG_LST:
-			{
-				char ***listp1 = (char ***)p1;
-				char ***listp2 = (char ***)p2;
-
-				if (!cmp_list(*listp1, *listp2))
-				{
-					return FALSE;
-				}
-			}
-			break;
-		default:
-			break;
+			default:
+				break;
 		}
 	}
 	return TRUE;
diff --git a/src/starter/args.h b/src/starter/args.h
index f5c13e6..76c05de 100644
--- a/src/starter/args.h
+++ b/src/starter/args.h
@@ -1,6 +1,6 @@
-/* automatic handling of confread struct arguments
+/*
  * Copyright (C) 2006 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+ * 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
@@ -17,16 +17,11 @@
 #define _ARGS_H_
 
 #include "keywords.h"
-#include "ipsec-parser.h"
 
-extern char **new_list(char *value);
-extern bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw
-	, char *base, bool *assigned);
-extern void free_args(kw_token_t first, kw_token_t last, char *base);
-extern void clone_args(kw_token_t first, kw_token_t last, char *base1
-	, char *base2);
-extern bool cmp_args(kw_token_t first, kw_token_t last, char *base1
-	, char *base2);
+bool assign_arg(kw_token_t token, kw_token_t first, char *key, char *value,
+				void *base, bool *assigned);
+void free_args(kw_token_t first, kw_token_t last, void *base);
+bool cmp_args(kw_token_t first, kw_token_t last, void *base1, void *base2);
 
 #endif /* _ARGS_H_ */
 
diff --git a/src/starter/confread.c b/src/starter/confread.c
index 19178a2..17dca66 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -1,4 +1,7 @@
-/* strongSwan IPsec config file parser
+/*
+ * Copyright (C) 2014 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -28,18 +31,25 @@
 #include "confread.h"
 #include "args.h"
 #include "files.h"
+#include "parser/conf_parser.h"
 
 #define IKE_LIFETIME_DEFAULT         10800 /* 3 hours */
 #define IPSEC_LIFETIME_DEFAULT        3600 /* 1 hour */
 #define SA_REPLACEMENT_MARGIN_DEFAULT  540 /* 9 minutes */
 #define SA_REPLACEMENT_FUZZ_DEFAULT    100 /* 100% of margin */
 #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 firewall_defaults[] = IPSEC_SCRIPT " _updown iptables";
 
+/**
+ * Provided by GPERF
+ */
+extern kw_entry_t *in_word_set (char *str, unsigned int len);
+
 static bool daemon_exists(char *daemon, char *path)
 {
 	struct stat st;
@@ -54,24 +64,21 @@ static bool daemon_exists(char *daemon, char *path)
 /**
  * Process deprecated keywords
  */
-static bool is_deprecated(kw_token_t token, kw_list_t *kw, char *name)
+static bool is_deprecated(kw_token_t token, char *name, char *conn)
 {
 	switch (token)
 	{
 		case KW_SETUP_DEPRECATED:
 		case KW_PKCS11_DEPRECATED:
-			DBG1(DBG_APP, "# deprecated keyword '%s' in config setup",
-				 kw->entry->name);
+			DBG1(DBG_APP, "# deprecated keyword '%s' in config setup", name);
 			break;
 		case KW_CONN_DEPRECATED:
 		case KW_END_DEPRECATED:
 		case KW_PFS_DEPRECATED:
-			DBG1(DBG_APP, "# deprecated keyword '%s' in conn '%s'",
-				 kw->entry->name, name);
+			DBG1(DBG_APP, "# deprecated keyword '%s' in conn '%s'", name, conn);
 			break;
 		case KW_CA_DEPRECATED:
-			DBG1(DBG_APP, "# deprecated keyword '%s' in ca '%s'",
-				 kw->entry->name, name);
+			DBG1(DBG_APP, "# deprecated keyword '%s' in ca '%s'", name, conn);
 			break;
 		default:
 			return FALSE;
@@ -80,11 +87,11 @@ static bool is_deprecated(kw_token_t token, kw_list_t *kw, char *name)
 	switch (token)
 	{
 		case KW_PKCS11_DEPRECATED:
-			DBG1(DBG_APP, "  use the 'pkcs11' plugin instead", kw->entry->name);
+			DBG1(DBG_APP, "  use the 'pkcs11' plugin instead");
 			break;
 		case KW_PFS_DEPRECATED:
 			DBG1(DBG_APP, "  PFS is enabled by specifying a DH group in the "
-				 "'esp' cipher suite", kw->entry->name);
+				 "'esp' cipher suite");
 			break;
 		default:
 			break;
@@ -92,100 +99,54 @@ static bool is_deprecated(kw_token_t token, kw_list_t *kw, char *name)
 	return TRUE;
 }
 
-static void default_values(starter_config_t *cfg)
-{
-	if (cfg == NULL)
-		return;
-
-	memset(cfg, 0, sizeof(struct starter_config));
-
-	/* is there enough space for all seen flags? */
-	assert(KW_SETUP_LAST - KW_SETUP_FIRST <
-		sizeof(cfg->setup.seen) * BITS_PER_BYTE);
-	assert(KW_CONN_LAST  - KW_CONN_FIRST <
-		sizeof(cfg->conn_default.seen) * BITS_PER_BYTE);
-	assert(KW_END_LAST - KW_END_FIRST <
-		sizeof(cfg->conn_default.right.seen) * BITS_PER_BYTE);
-	assert(KW_CA_LAST - KW_CA_FIRST <
-		sizeof(cfg->ca_default.seen) * BITS_PER_BYTE);
-
-	cfg->setup.seen        = SEEN_NONE;
-	cfg->setup.uniqueids   = TRUE;
-
-#ifdef START_CHARON
-	cfg->setup.charonstart = TRUE;
-#endif
-
-	cfg->conn_default.seen    = SEEN_NONE;
-	cfg->conn_default.startup = STARTUP_NO;
-	cfg->conn_default.state   = STATE_IGNORE;
-	cfg->conn_default.mode    = MODE_TUNNEL;
-	cfg->conn_default.options = SA_OPTION_MOBIKE;
-
-	cfg->conn_default.ike                   = strdupnull(ike_defaults);
-	cfg->conn_default.esp                   = strdupnull(esp_defaults);
-	cfg->conn_default.sa_ike_life_seconds   = IKE_LIFETIME_DEFAULT;
-	cfg->conn_default.sa_ipsec_life_seconds = IPSEC_LIFETIME_DEFAULT;
-	cfg->conn_default.sa_rekey_margin       = SA_REPLACEMENT_MARGIN_DEFAULT;
-	cfg->conn_default.sa_rekey_fuzz         = SA_REPLACEMENT_FUZZ_DEFAULT;
-	cfg->conn_default.sa_keying_tries       = SA_REPLACEMENT_RETRIES_DEFAULT;
-	cfg->conn_default.install_policy        = TRUE;
-	cfg->conn_default.dpd_delay             =  30; /* seconds */
-	cfg->conn_default.dpd_timeout           = 150; /* seconds */
-
-	cfg->conn_default.left.seen  = SEEN_NONE;
-	cfg->conn_default.right.seen = SEEN_NONE;
-
-	cfg->conn_default.left.sendcert  = CERT_SEND_IF_ASKED;
-	cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED;
-
-	cfg->conn_default.left.ikeport = 500;
-	cfg->conn_default.right.ikeport = 500;
-
-	cfg->conn_default.left.to_port = 0xffff;
-	cfg->conn_default.right.to_port = 0xffff;
-
-	cfg->ca_default.seen = SEEN_NONE;
-}
-
-#define KW_SA_OPTION_FLAG(sy, sn, fl) \
-		if (streq(kw->value, sy)) { conn->options |= fl; } \
-		else if (streq(kw->value, sn)) { conn->options &= ~fl; } \
-		else { DBG1(DBG_APP, "# bad option value: %s=%s", kw->entry->name, kw->value); cfg->err++; }
-
-static void load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
+/*
+ * parse config setup section
+ */
+static void load_setup(starter_config_t *cfg, conf_parser_t *parser)
 {
-	kw_list_t *kw;
+	enumerator_t *enumerator;
+	dictionary_t *dict;
+	kw_entry_t *entry;
+	char *key, *value;
 
 	DBG2(DBG_APP, "Loading config setup");
-
-	for (kw = cfgp->config_setup; kw; kw = kw->next)
+	dict = parser->get_section(parser, CONF_PARSER_CONFIG_SETUP, NULL);
+	if (!dict)
+	{
+		return;
+	}
+	enumerator = dict->create_enumerator(dict);
+	while (enumerator->enumerate(enumerator, &key, &value))
 	{
 		bool assigned = FALSE;
 
-		kw_token_t token = kw->entry->token;
-
-		if ((int)token < KW_SETUP_FIRST || token > KW_SETUP_LAST)
+		entry = in_word_set(key, strlen(key));
+		if (!entry)
 		{
-			DBG1(DBG_APP, "# unsupported keyword '%s' in config setup",
-				 kw->entry->name);
+			DBG1(DBG_APP, "# unknown keyword '%s'", key);
+			cfg->non_fatal_err++;
+			continue;
+		}
+		if ((int)entry->token < KW_SETUP_FIRST || entry->token > KW_SETUP_LAST)
+		{
+			DBG1(DBG_APP, "# unsupported keyword '%s' in config setup", key);
 			cfg->err++;
 			continue;
 		}
-
-		if (is_deprecated(token, kw, ""))
+		if (is_deprecated(entry->token, key, ""))
 		{
 			cfg->non_fatal_err++;
 			continue;
 		}
-
-		if (!assign_arg(token, KW_SETUP_FIRST, kw, (char *)cfg, &assigned))
+		if (!assign_arg(entry->token, KW_SETUP_FIRST, key, value, cfg,
+						&assigned))
 		{
 			DBG1(DBG_APP, "  bad argument value in config setup");
 			cfg->err++;
-			continue;
 		}
 	}
+	enumerator->destroy(enumerator);
+	dict->destroy(dict);
 
 	/* verify the executables are actually available */
 #ifdef START_CHARON
@@ -196,292 +157,321 @@ static void load_setup(starter_config_t *cfg, config_parsed_t *cfgp)
 #endif
 }
 
+/*
+ * parse a ca section
+ */
+static void load_ca(starter_ca_t *ca, starter_config_t *cfg,
+					conf_parser_t *parser)
+{
+	enumerator_t *enumerator;
+	dictionary_t *dict;
+	kw_entry_t *entry;
+	kw_token_t token;
+	char *key, *value;
+
+	DBG2(DBG_APP, "Loading ca '%s'", ca->name);
+	dict = parser->get_section(parser, CONF_PARSER_CA, ca->name);
+	if (!dict)
+	{
+		return;
+	}
+	enumerator = dict->create_enumerator(dict);
+	while (enumerator->enumerate(enumerator, &key, &value))
+	{
+		bool assigned = FALSE;
+
+		entry = in_word_set(key, strlen(key));
+		if (!entry)
+		{
+			DBG1(DBG_APP, "# unknown keyword '%s'", key);
+			cfg->non_fatal_err++;
+			continue;
+		}
+		token = entry->token;
+		if (token == KW_AUTO)
+		{
+			token = KW_CA_SETUP;
+		}
+		if (token < KW_CA_FIRST || token > KW_CA_LAST)
+		{
+			DBG1(DBG_APP, "# unsupported keyword '%s' in ca '%s'",
+				 key, ca->name);
+			cfg->err++;
+			continue;
+		}
+		if (is_deprecated(token, key, ca->name))
+		{
+			cfg->non_fatal_err++;
+			continue;
+		}
+		if (!assign_arg(token, KW_CA_FIRST, key, value, ca, &assigned))
+		{
+			DBG1(DBG_APP, "  bad argument value in ca '%s'", ca->name);
+			cfg->err++;
+		}
+	}
+	enumerator->destroy(enumerator);
+	dict->destroy(dict);
+
+	/* treat 'route' and 'start' as 'add' */
+	if (ca->startup != STARTUP_NO)
+	{
+		ca->startup = STARTUP_ADD;
+	}
+}
+
+/*
+ * set some default values
+ */
+static void conn_defaults(starter_conn_t *conn)
+{
+	conn->startup = STARTUP_NO;
+	conn->state   = STATE_IGNORE;
+	conn->mode    = MODE_TUNNEL;
+	conn->options = SA_OPTION_MOBIKE;
+
+	conn->ike                   = strdupnull(ike_defaults);
+	/* esp defaults are set after parsing the conn section */
+	conn->sa_ike_life_seconds   = IKE_LIFETIME_DEFAULT;
+	conn->sa_ipsec_life_seconds = IPSEC_LIFETIME_DEFAULT;
+	conn->sa_rekey_margin       = SA_REPLACEMENT_MARGIN_DEFAULT;
+	conn->sa_rekey_fuzz         = SA_REPLACEMENT_FUZZ_DEFAULT;
+	conn->sa_keying_tries       = SA_REPLACEMENT_RETRIES_DEFAULT;
+	conn->install_policy        = TRUE;
+	conn->dpd_delay             =  30; /* seconds */
+	conn->dpd_timeout           = 150; /* seconds */
+	conn->replay_window         = SA_REPLAY_WINDOW_DEFAULT;
+
+	conn->left.sendcert = CERT_SEND_IF_ASKED;
+	conn->right.sendcert = CERT_SEND_IF_ASKED;
+
+	conn->left.ikeport = 500;
+	conn->right.ikeport = 500;
+
+	conn->left.to_port = 0xffff;
+	conn->right.to_port = 0xffff;
+}
+
+/*
+ * parse left|right specific options
+ */
 static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
-				   kw_list_t *kw, char *conn_name, starter_config_t *cfg)
+				   char *key, char *value, starter_config_t *cfg)
 {
 	bool assigned = FALSE;
 
-	char *name  = kw->entry->name;
-	char *value = kw->value;
-
-	if (is_deprecated(token, kw, conn_name))
+	if (is_deprecated(token, key, conn->name))
 	{
 		cfg->non_fatal_err++;
 		return;
 	}
 
-	if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned))
+	if (!assign_arg(token, KW_END_FIRST, key, value, end, &assigned))
+	{
 		goto err;
+	}
 
 	/* post processing of some keywords that were assigned automatically */
 	switch (token)
 	{
-	case KW_HOST:
-		if (value && strlen(value) > 0 && value[0] == '%')
-		{
-			if (streq(value, "%defaultroute"))
+		case KW_HOST:
+			if (value && strlen(value) > 0 && value[0] == '%')
 			{
-				value = "%any";
+				if (streq(value, "%defaultroute"))
+				{
+					value = "%any";
+				}
+				if (!streq(value, "%any") && !streq(value, "%any4") &&
+					!streq(value, "%any6"))
+				{	/* allow_any prefix */
+					end->allow_any = TRUE;
+					value++;
+				}
 			}
-			if (!streq(value, "%any") && !streq(value, "%any4") &&
-				!streq(value, "%any6"))
-			{	/* allow_any prefix */
-				end->allow_any = TRUE;
-				value++;
+			free(end->host);
+			end->host = strdupnull(value);
+			break;
+		case KW_SOURCEIP:
+			conn->mode = MODE_TUNNEL;
+			conn->proxy_mode = FALSE;
+			break;
+		case KW_SENDCERT:
+			if (end->sendcert == CERT_YES_SEND)
+			{
+				end->sendcert = CERT_ALWAYS_SEND;
 			}
-		}
-		free(end->host);
-		end->host = strdupnull(value);
-		break;
-	case KW_SOURCEIP:
-		conn->mode = MODE_TUNNEL;
-		conn->proxy_mode = FALSE;
-		break;
-	case KW_SENDCERT:
-		if (end->sendcert == CERT_YES_SEND)
-		{
-			end->sendcert = CERT_ALWAYS_SEND;
-		}
-		else if (end->sendcert == CERT_NO_SEND)
-		{
-			end->sendcert = CERT_NEVER_SEND;
-		}
-		break;
-	default:
-		break;
+			else if (end->sendcert == CERT_NO_SEND)
+			{
+				end->sendcert = CERT_NEVER_SEND;
+			}
+			break;
+		default:
+			break;
 	}
 
 	if (assigned)
+	{
 		return;
+	}
 
 	/* individual processing of keywords that were not assigned automatically */
 	switch (token)
 	{
-	case KW_PROTOPORT:
-	{
-		struct protoent *proto;
-		struct servent *svc;
-		char *sep, *port = "", *endptr;
-		long int p;
-
-		sep = strchr(value, '/');
-		if (sep)
-		{	/* protocol/port */
-			*sep = '\0';
-			port = sep + 1;
-		}
+		case KW_PROTOPORT:
+		{
+			struct protoent *proto;
+			struct servent *svc;
+			char *sep, *port = "", *endptr;
+			long int p;
+
+			sep = strchr(value, '/');
+			if (sep)
+			{	/* protocol/port */
+				*sep = '\0';
+				port = sep + 1;
+			}
 
-		if (streq(value, "%any"))
-		{
-			end->protocol = 0;
-		}
-		else
-		{
-			proto = getprotobyname(value);
-			if (proto)
+			if (streq(value, "%any"))
 			{
-				end->protocol = proto->p_proto;
+				end->protocol = 0;
 			}
 			else
 			{
-				p = strtol(value, &endptr, 0);
-				if ((*value && *endptr) || p < 0 || p > 0xff)
+				proto = getprotobyname(value);
+				if (proto)
+				{
+					end->protocol = proto->p_proto;
+				}
+				else
 				{
-					DBG1(DBG_APP, "# bad protocol: %s=%s", name, value);
-					goto err;
+					p = strtol(value, &endptr, 0);
+					if ((*value && *endptr) || p < 0 || p > 0xff)
+					{
+						DBG1(DBG_APP, "# bad protocol: %s=%s", key, value);
+						goto err;
+					}
+					end->protocol = (u_int8_t)p;
 				}
-				end->protocol = (u_int8_t)p;
 			}
-		}
-		if (streq(port, "%any"))
-		{
-			end->from_port = 0;
-			end->to_port = 0xffff;
-		}
-		else if (streq(port, "%opaque"))
-		{
-			end->from_port = 0xffff;
-			end->to_port = 0;
-		}
-		else if (*port)
-		{
-			svc = getservbyname(port, NULL);
-			if (svc)
+			if (streq(port, "%any"))
 			{
-				end->from_port = end->to_port = ntohs(svc->s_port);
+				end->from_port = 0;
+				end->to_port = 0xffff;
 			}
-			else
+			else if (streq(port, "%opaque"))
+			{
+				end->from_port = 0xffff;
+				end->to_port = 0;
+			}
+			else if (*port)
 			{
-				p = strtol(port, &endptr, 0);
-				if (p < 0 || p > 0xffff)
+				svc = getservbyname(port, NULL);
+				if (svc)
 				{
-					DBG1(DBG_APP, "# bad port: %s=%s", name, port);
-					goto err;
+					end->from_port = end->to_port = ntohs(svc->s_port);
 				}
-				end->from_port = p;
-				if (*endptr == '-')
+				else
 				{
-					port = endptr + 1;
 					p = strtol(port, &endptr, 0);
 					if (p < 0 || p > 0xffff)
 					{
-						DBG1(DBG_APP, "# bad port: %s=%s", name, port);
+						DBG1(DBG_APP, "# bad port: %s=%s", key, port);
+						goto err;
+					}
+					end->from_port = p;
+					if (*endptr == '-')
+					{
+						port = endptr + 1;
+						p = strtol(port, &endptr, 0);
+						if (p < 0 || p > 0xffff)
+						{
+							DBG1(DBG_APP, "# bad port: %s=%s", key, port);
+							goto err;
+						}
+					}
+					end->to_port = p;
+					if (*endptr)
+					{
+						DBG1(DBG_APP, "# bad port: %s=%s", key, port);
 						goto err;
 					}
-				}
-				end->to_port = p;
-				if (*endptr)
-				{
-					DBG1(DBG_APP, "# bad port: %s=%s", name, port);
-					goto err;
 				}
 			}
+			if (sep)
+			{	/* restore the original text in case also= is used */
+				*sep = '/';
+			}
+			break;
 		}
-		if (sep)
-		{	/* restore the original text in case also= is used */
-			*sep = '/';
-		}
-		break;
-	}
-	default:
-		break;
+		default:
+			break;
 	}
 	return;
 
 err:
-	DBG1(DBG_APP, "  bad argument value in conn '%s'", conn_name);
+	DBG1(DBG_APP, "  bad argument value in conn '%s'", conn->name);
 	cfg->err++;
 }
 
 /*
- * handles left|rightfirewall and left|rightupdown parameters
+ * macro to handle simple flags
  */
-static void handle_firewall(const char *label, starter_end_t *end,
-							starter_config_t *cfg)
-{
-	if (end->firewall && (end->seen & SEEN_KW(KW_FIREWALL, KW_END_FIRST)))
-	{
-		if (end->updown != NULL)
-		{
-			DBG1(DBG_APP, "# cannot have both %sfirewall and %supdown", label,
-				 label);
-			cfg->err++;
-		}
-		else
-		{
-			end->updown = strdupnull(firewall_defaults);
-			end->firewall = FALSE;
-		}
-	}
-}
+#define KW_SA_OPTION_FLAG(sy, sn, fl) \
+		if (streq(value, sy)) { conn->options |= fl; } \
+		else if (streq(value, sn)) { conn->options &= ~fl; } \
+		else { DBG1(DBG_APP, "# bad option value: %s=%s", key, value); cfg->err++; }
 
 /*
- * parse a conn section
+ * parse settings not handled by the simple argument parser
  */
-static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg)
+static void handle_keyword(kw_token_t token, starter_conn_t *conn, char *key,
+						   char *value, starter_config_t *cfg)
 {
-	char *conn_name = (conn->name == NULL)? "%default":conn->name;
-
-	for ( ; kw; kw = kw->next)
+	if ((token == KW_ESP && conn->ah) || (token == KW_AH && conn->esp))
+	{
+		DBG1(DBG_APP, "# can't have both 'ah' and 'esp' options");
+		cfg->err++;
+		return;
+	}
+	switch (token)
 	{
-		bool assigned = FALSE;
-
-		kw_token_t token = kw->entry->token;
-
-		if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST)
-		{
-			kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST
-				,  kw, conn_name, cfg);
-			continue;
-		}
-		else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST)
-		{
-			kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST
-				 , kw, conn_name, cfg);
-			continue;
-		}
-
-		if (token == KW_AUTO)
-		{
-			token = KW_CONN_SETUP;
-		}
-		else if (token == KW_ALSO)
-		{
-			if (cfg->parse_also)
-			{
-				also_t *also = malloc_thing(also_t);
-
-				also->name = strdupnull(kw->value);
-				also->next = conn->also;
-				conn->also = also;
-
-				DBG2(DBG_APP, "  also=%s", kw->value);
-			}
-			continue;
-		}
-
-		if (token < KW_CONN_FIRST || token > KW_CONN_LAST)
-		{
-			DBG1(DBG_APP, "# unsupported keyword '%s' in conn '%s'",
-				 kw->entry->name, conn_name);
-			cfg->err++;
-			continue;
-		}
-
-		if (is_deprecated(token, kw, conn_name))
-		{
-			cfg->non_fatal_err++;
-			continue;
-		}
-
-		if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned))
-		{
-			DBG1(DBG_APP, "  bad argument value in conn '%s'", conn_name);
-			cfg->err++;
-			continue;
-		}
-
-		if (assigned)
-			continue;
-
-		switch (token)
-		{
 		case KW_TYPE:
+		{
 			conn->mode = MODE_TRANSPORT;
 			conn->proxy_mode = FALSE;
-			if (streq(kw->value, "tunnel"))
+			if (streq(value, "tunnel"))
 			{
 				conn->mode = MODE_TUNNEL;
 			}
-			else if (streq(kw->value, "beet"))
+			else if (streq(value, "beet"))
 			{
 				conn->mode = MODE_BEET;
 			}
-			else if (streq(kw->value, "transport_proxy"))
+			else if (streq(value, "transport_proxy"))
 			{
 				conn->mode = MODE_TRANSPORT;
 				conn->proxy_mode = TRUE;
 			}
-			else if (streq(kw->value, "passthrough") || streq(kw->value, "pass"))
+			else if (streq(value, "passthrough") || streq(value, "pass"))
 			{
 				conn->mode = MODE_PASS;
 			}
-			else if (streq(kw->value, "drop") || streq(kw->value, "reject"))
+			else if (streq(value, "drop") || streq(value, "reject"))
 			{
 				conn->mode = MODE_DROP;
 			}
-			else if (!streq(kw->value, "transport"))
+			else if (!streq(value, "transport"))
 			{
-				DBG1(DBG_APP, "# bad policy value: %s=%s", kw->entry->name,
-					 kw->value);
+				DBG1(DBG_APP, "# bad policy value: %s=%s", key, value);
 				cfg->err++;
 			}
 			break;
+		}
 		case KW_COMPRESS:
 			KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_COMPRESS)
 			break;
 		case KW_MARK:
-			if (!mark_from_string(kw->value, &conn->mark_in))
+			if (!mark_from_string(value, &conn->mark_in))
 			{
 				cfg->err++;
 				break;
@@ -489,19 +479,19 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
 			conn->mark_out = conn->mark_in;
 			break;
 		case KW_MARK_IN:
-			if (!mark_from_string(kw->value, &conn->mark_in))
+			if (!mark_from_string(value, &conn->mark_in))
 			{
 				cfg->err++;
 			}
 			break;
 		case KW_MARK_OUT:
-			if (!mark_from_string(kw->value, &conn->mark_out))
+			if (!mark_from_string(value, &conn->mark_out))
 			{
 				cfg->err++;
 			}
 			break;
 		case KW_TFC:
-			if (streq(kw->value, "%mtu"))
+			if (streq(value, "%mtu"))
 			{
 				conn->tfc = -1;
 			}
@@ -509,17 +499,16 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
 			{
 				char *endptr;
 
-				conn->tfc = strtoul(kw->value, &endptr, 10);
+				conn->tfc = strtoul(value, &endptr, 10);
 				if (*endptr != '\0')
 				{
-					DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
-						 kw->value);
+					DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
 					cfg->err++;
 				}
 			}
 			break;
 		case KW_KEYINGTRIES:
-			if (streq(kw->value, "%forever"))
+			if (streq(value, "%forever"))
 			{
 				conn->sa_keying_tries = 0;
 			}
@@ -527,11 +516,10 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
 			{
 				char *endptr;
 
-				conn->sa_keying_tries = strtoul(kw->value, &endptr, 10);
+				conn->sa_keying_tries = strtoul(value, &endptr, 10);
 				if (*endptr != '\0')
 				{
-					DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name,
-						 kw->value);
+					DBG1(DBG_APP, "# bad integer value: %s=%s", key, value);
 					cfg->err++;
 				}
 			}
@@ -556,219 +544,120 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
 			break;
 		default:
 			break;
-		}
 	}
-
-	handle_firewall("left", &conn->left, cfg);
-	handle_firewall("right", &conn->right, cfg);
 }
 
 /*
- * initialize a conn object with the default conn
+ * handles left|rightfirewall and left|rightupdown parameters
  */
-static void conn_default(char *name, starter_conn_t *conn, starter_conn_t *def)
+static void handle_firewall(const char *label, starter_end_t *end,
+							starter_config_t *cfg)
 {
-	memcpy(conn, def, sizeof(starter_conn_t));
-	conn->name = strdupnull(name);
-
-	clone_args(KW_CONN_FIRST, KW_CONN_LAST, (char *)conn, (char *)def);
-	clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left, (char *)&def->left);
-	clone_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right, (char *)&def->right);
+	if (end->firewall)
+	{
+		if (end->updown != NULL)
+		{
+			DBG1(DBG_APP, "# cannot have both %sfirewall and %supdown", label,
+				 label);
+			cfg->err++;
+		}
+		else
+		{
+			end->updown = strdupnull(firewall_defaults);
+			end->firewall = FALSE;
+		}
+	}
 }
 
 /*
- * parse a ca section
+ * parse a conn section
  */
-static void load_ca(starter_ca_t *ca, kw_list_t *kw, starter_config_t *cfg)
+static void load_conn(starter_conn_t *conn, starter_config_t *cfg,
+					  conf_parser_t *parser)
 {
-	char *ca_name = (ca->name == NULL)? "%default":ca->name;
-
-	for ( ; kw; kw = kw->next)
+	enumerator_t *enumerator;
+	dictionary_t *dict;
+	kw_entry_t *entry;
+	kw_token_t token;
+	char *key, *value;
+
+	DBG2(DBG_APP, "Loading conn '%s'", conn->name);
+	dict = parser->get_section(parser, CONF_PARSER_CONN, conn->name);
+	if (!dict)
+	{
+		return;
+	}
+	enumerator = dict->create_enumerator(dict);
+	while (enumerator->enumerate(enumerator, &key, &value))
 	{
 		bool assigned = FALSE;
 
-		kw_token_t token = kw->entry->token;
-
-		if (token == KW_AUTO)
-		{
-			token = KW_CA_SETUP;
-		}
-		else if (token == KW_ALSO)
+		entry = in_word_set(key, strlen(key));
+		if (!entry)
 		{
-			if (cfg->parse_also)
-			{
-				also_t *also = malloc_thing(also_t);
-
-				also->name = strdupnull(kw->value);
-				also->next = ca->also;
-				ca->also = also;
-
-				DBG2(DBG_APP, "  also=%s", kw->value);
-			}
+			DBG1(DBG_APP, "# unknown keyword '%s'", key);
+			cfg->non_fatal_err++;
 			continue;
 		}
-
-		if (token < KW_CA_FIRST || token > KW_CA_LAST)
+		token = entry->token;
+		if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST)
 		{
-			DBG1(DBG_APP, "# unsupported keyword '%s' in ca '%s'",
-				 kw->entry->name, ca_name);
-			cfg->err++;
+			kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST,
+				   key, value, cfg);
 			continue;
 		}
-
-		if (is_deprecated(token, kw, ca_name))
+		else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST)
 		{
-			cfg->non_fatal_err++;
+			kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST,
+				   key, value, cfg);
 			continue;
 		}
-
-		if (!assign_arg(token, KW_CA_FIRST, kw, (char *)ca, &assigned))
-		{
-			DBG1(DBG_APP, "  bad argument value in ca '%s'", ca_name);
-			cfg->err++;
-		}
-	}
-
-	/* treat 'route' and 'start' as 'add' */
-	if (ca->startup != STARTUP_NO)
-		ca->startup = STARTUP_ADD;
-}
-
-/*
- * initialize a ca object with the default ca
- */
-static void ca_default(char *name, starter_ca_t *ca, starter_ca_t *def)
-{
-	memcpy(ca, def, sizeof(starter_ca_t));
-	ca->name = strdupnull(name);
-
-	clone_args(KW_CA_FIRST, KW_CA_LAST, (char *)ca, (char *)def);
-}
-
-static kw_list_t* find_also_conn(const char* name, starter_conn_t *conn,
-								 starter_config_t *cfg);
-
-static void load_also_conns(starter_conn_t *conn, also_t *also,
-							starter_config_t *cfg)
-{
-	while (also != NULL)
-	{
-		kw_list_t *kw = find_also_conn(also->name, conn, cfg);
-
-		if (kw == NULL)
+		if (token == KW_AUTO)
 		{
-			DBG1(DBG_APP, "  conn '%s' cannot include '%s'", conn->name,
-				 also->name);
+			token = KW_CONN_SETUP;
 		}
-		else
+		if (token < KW_CONN_FIRST || token > KW_CONN_LAST)
 		{
-			DBG2(DBG_APP, "conn '%s' includes '%s'", conn->name, also->name);
-			/* only load if no error occurred in the first round */
-			if (cfg->err == 0)
-				load_conn(conn, kw, cfg);
+			DBG1(DBG_APP, "# unsupported keyword '%s' in conn '%s'",
+				 key, conn->name);
+			cfg->err++;
+			continue;
 		}
-		also = also->next;
-	}
-}
-
-/*
- * find a conn included by also
- */
-static kw_list_t* find_also_conn(const char* name, starter_conn_t *conn,
-								 starter_config_t *cfg)
-{
-	starter_conn_t *c = cfg->conn_first;
-
-	while (c != NULL)
-	{
-		if (streq(name, c->name))
+		if (is_deprecated(token, key, conn->name))
 		{
-			if (conn->visit == c->visit)
-			{
-				DBG1(DBG_APP, "# detected also loop");
-				cfg->err++;
-				return NULL;
-			}
-			c->visit = conn->visit;
-			load_also_conns(conn, c->also, cfg);
-			return c->kw;
+			cfg->non_fatal_err++;
+			continue;
 		}
-		c = c->next;
-	}
-
-	DBG1(DBG_APP, "# also '%s' not found", name);
-	cfg->err++;
-	return NULL;
-}
-
-static kw_list_t* find_also_ca(const char* name, starter_ca_t *ca,
-							   starter_config_t *cfg);
-
-static void load_also_cas(starter_ca_t *ca, also_t *also, starter_config_t *cfg)
-{
-	while (also != NULL)
-	{
-		kw_list_t *kw = find_also_ca(also->name, ca, cfg);
-
-		if (kw == NULL)
+		if (!assign_arg(token, KW_CONN_FIRST, key, value, conn,
+						&assigned))
 		{
-			DBG1(DBG_APP, "  ca '%s' cannot include '%s'", ca->name,
-				 also->name);
+			DBG1(DBG_APP, "  bad argument value in conn '%s'", conn->name);
+			cfg->err++;
+			continue;
 		}
-		else
+		if (!assigned)
 		{
-			DBG2(DBG_APP, "ca '%s' includes '%s'", ca->name, also->name);
-			/* only load if no error occurred in the first round */
-			if (cfg->err == 0)
-			load_ca(ca, kw, cfg);
+			handle_keyword(token, conn, key, value, cfg);
 		}
-		also = also->next;
 	}
-}
+	enumerator->destroy(enumerator);
+	dict->destroy(dict);
 
-/*
- * find a ca included by also
- */
-static kw_list_t* find_also_ca(const char* name, starter_ca_t *ca,
-							   starter_config_t *cfg)
-{
-	starter_ca_t *c = cfg->ca_first;
+	handle_firewall("left", &conn->left, cfg);
+	handle_firewall("right", &conn->right, cfg);
 
-	while (c != NULL)
+	if (!conn->esp && !conn->ah)
 	{
-		if (streq(name, c->name))
-		{
-			if (ca->visit == c->visit)
-			{
-				DBG1(DBG_APP, "# detected also loop");
-				cfg->err++;
-				return NULL;
-			}
-			c->visit = ca->visit;
-			load_also_cas(ca, c->also, cfg);
-			return c->kw;
-		}
-		c = c->next;
+		conn->esp = strdupnull(esp_defaults);
 	}
-
-	DBG1(DBG_APP, "# also '%s' not found", name);
-	cfg->err++;
-	return NULL;
 }
 
 /*
- * free the memory used by also_t objects
+ * free the memory used by a starter_ca_t object
  */
-static void free_also(also_t *head)
+static void confread_free_ca(starter_ca_t *ca)
 {
-	while (head != NULL)
-	{
-		also_t *also = head;
-
-		head = also->next;
-		free(also->name);
-		free(also);
-	}
+	free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca);
 }
 
 /*
@@ -779,17 +668,6 @@ static void confread_free_conn(starter_conn_t *conn)
 	free_args(KW_END_FIRST, KW_END_LAST,  (char *)&conn->left);
 	free_args(KW_END_FIRST, KW_END_LAST,  (char *)&conn->right);
 	free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn);
-	free_also(conn->also);
-}
-
-/*
- * free the memory used by a starter_ca_t object
- */
-static void
-confread_free_ca(starter_ca_t *ca)
-{
-	free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca);
-	free_also(ca->also);
 }
 
 /*
@@ -802,8 +680,6 @@ void confread_free(starter_config_t *cfg)
 
 	free_args(KW_SETUP_FIRST, KW_SETUP_LAST, (char *)cfg);
 
-	confread_free_conn(&cfg->conn_default);
-
 	while (conn != NULL)
 	{
 		starter_conn_t *conn_aux = conn;
@@ -813,8 +689,6 @@ void confread_free(starter_config_t *cfg)
 		free(conn_aux);
 	}
 
-	confread_free_ca(&cfg->ca_default);
-
 	while (ca != NULL)
 	{
 		starter_ca_t *ca_aux = ca;
@@ -832,170 +706,108 @@ void confread_free(starter_config_t *cfg)
  */
 starter_config_t* confread_load(const char *file)
 {
+	conf_parser_t *parser;
 	starter_config_t *cfg = NULL;
-	config_parsed_t  *cfgp;
-	section_list_t   *sconn, *sca;
-	starter_conn_t   *conn;
-	starter_ca_t     *ca;
-
+	enumerator_t *enumerator;
 	u_int total_err;
-	u_int visit	= 0;
+	char *name;
 
-	/* load IPSec configuration file  */
-	cfgp = parser_load_conf(file);
-	if (!cfgp)
+	parser = conf_parser_create(file);
+	if (!parser->parse(parser))
 	{
+		parser->destroy(parser);
 		return NULL;
 	}
-	cfg = malloc_thing(starter_config_t);
-
-	/* set default values */
-	default_values(cfg);
-
-	/* load config setup section */
-	load_setup(cfg, cfgp);
 
-	/* in the first round parse also statements */
-	cfg->parse_also = TRUE;
+	INIT(cfg,
+		.setup = {
+			.uniqueids = TRUE,
 
-	/* find %default ca section */
-	for (sca = cfgp->ca_first; sca; sca = sca->next)
-	{
-		if (streq(sca->name, "%default"))
-		{
-			DBG2(DBG_APP, "Loading ca %%default");
-			load_ca(&cfg->ca_default, sca->kw, cfg);
 		}
-	}
+	);
+#ifdef START_CHARON
+	cfg->setup.charonstart = TRUE;
+#endif
 
-	/* parameters defined in ca %default sections can be overloads */
-	cfg->ca_default.seen = SEEN_NONE;
+	/* load config setup section */
+	load_setup(cfg, parser);
 
-	/* load other ca sections */
-	for (sca = cfgp->ca_first; sca; sca = sca->next)
+	/* load ca sections */
+	enumerator = parser->get_sections(parser, CONF_PARSER_CA);
+	while (enumerator->enumerate(enumerator, &name))
 	{
-		u_int previous_err;
+		u_int previous_err = cfg->err;
+		starter_ca_t *ca;
 
-		/* skip %default ca section */
-		if (streq(sca->name, "%default"))
-			continue;
-
-		DBG2(DBG_APP, "Loading ca '%s'", sca->name);
-		ca = malloc_thing(starter_ca_t);
-
-		ca_default(sca->name, ca, &cfg->ca_default);
-		ca->kw =  sca->kw;
-		ca->next = NULL;
+		INIT(ca,
+			.name = strdup(name),
+		);
+		load_ca(ca, cfg, parser);
 
-		previous_err = cfg->err;
-		load_ca(ca, ca->kw, cfg);
 		if (cfg->err > previous_err)
 		{
-			/* errors occurred - free the ca */
 			confread_free_ca(ca);
 			cfg->non_fatal_err += cfg->err - previous_err;
 			cfg->err = previous_err;
 		}
 		else
 		{
-			/* success - insert the ca into the chained list */
 			if (cfg->ca_last)
+			{
 				cfg->ca_last->next = ca;
+			}
 			cfg->ca_last = ca;
 			if (!cfg->ca_first)
+			{
 				cfg->ca_first = ca;
+			}
+			if (ca->startup != STARTUP_NO)
+			{
+				ca->state = STATE_TO_ADD;
+			}
 		}
 	}
+	enumerator->destroy(enumerator);
 
-	for (ca = cfg->ca_first; ca; ca = ca->next)
-	{
-		also_t *also = ca->also;
-
-		while (also != NULL)
-		{
-			kw_list_t *kw = find_also_ca(also->name, cfg->ca_first, cfg);
-
-			load_ca(ca, kw, cfg);
-			also = also->next;
-		}
-
-		if (ca->startup != STARTUP_NO)
-			ca->state = STATE_TO_ADD;
-	}
-
-	/* find %default conn sections */
-	for (sconn = cfgp->conn_first; sconn; sconn = sconn->next)
-	{
-		if (streq(sconn->name, "%default"))
-		{
-			DBG2(DBG_APP, "Loading conn %%default");
-			load_conn(&cfg->conn_default, sconn->kw, cfg);
-		}
-	}
-
-	/* parameters defined in conn %default sections can be overloaded */
-	cfg->conn_default.seen       = SEEN_NONE;
-	cfg->conn_default.right.seen = SEEN_NONE;
-	cfg->conn_default.left.seen  = SEEN_NONE;
-
-	/* load other conn sections */
-	for (sconn = cfgp->conn_first; sconn; sconn = sconn->next)
+	/* load conn sections */
+	enumerator = parser->get_sections(parser, CONF_PARSER_CONN);
+	while (enumerator->enumerate(enumerator, &name))
 	{
-		u_int previous_err;
-
-		/* skip %default conn section */
-		if (streq(sconn->name, "%default"))
-			continue;
-
-		DBG2(DBG_APP, "Loading conn '%s'", sconn->name);
-		conn = malloc_thing(starter_conn_t);
+		u_int previous_err = cfg->err;
+		starter_conn_t *conn;
 
-		conn_default(sconn->name, conn, &cfg->conn_default);
-		conn->kw =  sconn->kw;
-		conn->next = NULL;
+		INIT(conn,
+			.name = strdup(name),
+		);
+		conn_defaults(conn);
+		load_conn(conn, cfg, parser);
 
-		previous_err = cfg->err;
-		load_conn(conn, conn->kw, cfg);
 		if (cfg->err > previous_err)
 		{
-			/* error occurred - free the conn */
 			confread_free_conn(conn);
 			cfg->non_fatal_err += cfg->err - previous_err;
 			cfg->err = previous_err;
 		}
 		else
 		{
-			/* success - insert the conn into the chained list */
 			if (cfg->conn_last)
+			{
 				cfg->conn_last->next = conn;
+			}
 			cfg->conn_last = conn;
 			if (!cfg->conn_first)
+			{
 				cfg->conn_first = conn;
+			}
+			if (conn->startup != STARTUP_NO)
+			{
+				conn->state = STATE_TO_ADD;
+			}
 		}
 	}
+	enumerator->destroy(enumerator);
 
-	/* in the second round do not parse also statements */
-	cfg->parse_also = FALSE;
-
-	for (ca = cfg->ca_first; ca; ca = ca->next)
-	{
-		ca->visit = ++visit;
-		load_also_cas(ca, ca->also, cfg);
-
-		if (ca->startup != STARTUP_NO)
-			ca->state = STATE_TO_ADD;
-	}
-
-	for (conn = cfg->conn_first; conn; conn = conn->next)
-	{
-		conn->visit = ++visit;
-		load_also_conns(conn, conn->also, cfg);
-
-		if (conn->startup != STARTUP_NO)
-			conn->state = STATE_TO_ADD;
-	}
-
-	parser_free_conf(cfgp);
+	parser->destroy(parser);
 
 	total_err = cfg->err + cfg->non_fatal_err;
 	if (total_err > 0)
@@ -1003,6 +815,5 @@ starter_config_t* confread_load(const char *file)
 		DBG1(DBG_APP, "### %d parsing error%s (%d fatal) ###",
 			 total_err, (total_err > 1)?"s":"", cfg->err);
 	}
-
 	return cfg;
 }
diff --git a/src/starter/confread.h b/src/starter/confread.h
index d55a17e..0eea988 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -18,13 +18,6 @@
 
 #include <kernel/kernel_ipsec.h>
 
-#include "ipsec-parser.h"
-
-/** to mark seen keywords */
-typedef u_int64_t seen_t;
-#define SEEN_NONE 0;
-#define SEEN_KW(kw, base) ((seen_t)1 << ((kw) - (base)))
-
 typedef enum {
 		STARTUP_NO,
 		STARTUP_ADD,
@@ -92,7 +85,6 @@ typedef enum {
 typedef struct starter_end starter_end_t;
 
 struct starter_end {
-		seen_t          seen;
 		char            *auth;
 		char            *auth2;
 		char            *id;
@@ -121,22 +113,10 @@ struct starter_end {
 		char            *dns;
 };
 
-typedef struct also also_t;
-
-struct also {
-		char            *name;
-		bool            included;
-		also_t          *next;
-};
-
 typedef struct starter_conn starter_conn_t;
 
 struct starter_conn {
-		seen_t          seen;
 		char            *name;
-		also_t          *also;
-		kw_list_t       *kw;
-		u_int           visit;
 		startup_t       startup;
 		starter_state_t state;
 
@@ -162,6 +142,7 @@ struct starter_conn {
 		u_int32_t       reqid;
 		mark_t          mark_in;
 		mark_t          mark_out;
+		u_int32_t       replay_window;
 		u_int32_t       tfc;
 		bool            install_policy;
 		bool            aggressive;
@@ -192,11 +173,7 @@ struct starter_conn {
 typedef struct starter_ca starter_ca_t;
 
 struct starter_ca {
-		seen_t          seen;
 		char            *name;
-		also_t          *also;
-		kw_list_t       *kw;
-		u_int           visit;
 		startup_t       startup;
 		starter_state_t state;
 
@@ -216,7 +193,6 @@ typedef struct starter_config starter_config_t;
 
 struct starter_config {
 		struct {
-				seen_t  seen;
 				bool     charonstart;
 				char     *charondebug;
 				bool     uniqueids;
@@ -228,23 +204,14 @@ struct starter_config {
 		u_int err;
 		u_int non_fatal_err;
 
-		/* do we parse also statements */
-		bool parse_also;
-
-		/* ca %default */
-		starter_ca_t ca_default;
-
-		/* connections list (without %default) */
+		/* connections list */
 		starter_ca_t *ca_first, *ca_last;
 
-		/* conn %default */
-		starter_conn_t conn_default;
-
-		/* connections list (without %default) */
+		/* connections list */
 		starter_conn_t *conn_first, *conn_last;
 };
 
-extern starter_config_t *confread_load(const char *file);
-extern void confread_free(starter_config_t *cfg);
+starter_config_t *confread_load(const char *file);
+void confread_free(starter_config_t *cfg);
 
 #endif /* _IPSEC_CONFREAD_H_ */
diff --git a/src/starter/ipsec-parser.h b/src/starter/ipsec-parser.h
deleted file mode 100644
index 1c6cf20..0000000
--- a/src/starter/ipsec-parser.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* strongSwan config file parser
- * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#ifndef _IPSEC_PARSER_H_
-#define _IPSEC_PARSER_H_
-
-#include "keywords.h"
-
-typedef struct kw_entry kw_entry_t;
-
-struct kw_entry {
-	char *name;
-	kw_token_t token;
-};
-
-typedef struct kw_list kw_list_t;
-
-struct kw_list {
-		kw_entry_t *entry;
-		char *value;
-		kw_list_t *next;
-};
-
-typedef struct section_list section_list_t;
-
-struct section_list {
-		char *name;
-		kw_list_t *kw;
-		section_list_t *next;
-};
-
-typedef struct config_parsed config_parsed_t;
-
-struct config_parsed {
-		kw_list_t *config_setup;
-		section_list_t *conn_first, *conn_last;
-		section_list_t *ca_first, *ca_last;
-};
-
-config_parsed_t *parser_load_conf (const char *file);
-void parser_free_conf (config_parsed_t *cfg);
-
-#endif /* _IPSEC_PARSER_H_ */
-
diff --git a/src/starter/keywords.c b/src/starter/keywords.c
index d370c66..762c5d9 100644
--- a/src/starter/keywords.c
+++ b/src/starter/keywords.c
@@ -54,7 +54,7 @@ struct kw_entry {
     kw_token_t token;
 };
 
-#define TOTAL_KEYWORDS 138
+#define TOTAL_KEYWORDS 139
 #define MIN_WORD_LENGTH 2
 #define MAX_WORD_LENGTH 17
 #define MIN_HASH_VALUE 9
@@ -84,9 +84,9 @@ hash (str, len)
       258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
       258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
       258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
-      258, 258, 258, 258, 258,   3, 258,  31,   1,  83,
+      258, 258, 258, 258, 258,   3, 258,  31,   4,  83,
        50,   5,   4,   1,  79,   1, 258, 121,  62,   5,
-       33,  51,  41,   2,  22,   1,  25, 103,   6, 258,
+       33,  51,  41,   2,  22,   1,  25, 103,   6,   1,
       258,   8,   2, 258, 258, 258, 258, 258, 258, 258,
       258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
       258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
@@ -156,9 +156,10 @@ static const struct kw_entry wordlist[] =
     {"reqid",             KW_REQID},
     {"certuribase",       KW_CERTURIBASE},
     {"leftnexthop",       KW_LEFT_DEPRECATED},
-    {"mobike",	           KW_MOBIKE},
+    {"replay_window",     KW_REPLAY_WINDOW},
     {"leftprotoport",     KW_LEFTPROTOPORT},
     {"compress",          KW_COMPRESS},
+    {"mobike",	           KW_MOBIKE},
     {"me_peerid",         KW_ME_PEERID},
     {"interfaces",        KW_SETUP_DEPRECATED},
     {"virtual_private",   KW_SETUP_DEPRECATED},
@@ -272,25 +273,25 @@ static const short lookup[] =
      14,  15,  16,  -1,  -1,  -1,  17,  18,  19,  20,
      21,  22,  -1,  23,  24,  -1,  25,  26,  27,  -1,
      28,  29,  30,  -1,  -1,  31,  32,  -1,  33,  34,
-     35,  -1,  36,  37,  38,  39,  -1,  40,  -1,  -1,
-     -1,  41,  42,  43,  44,  -1,  45,  -1,  46,  -1,
-     47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
-     57,  58,  -1,  -1,  59,  60,  61,  -1,  62,  -1,
-     63,  -1,  64,  65,  66,  67,  68,  69,  70,  71,
-     -1,  72,  73,  74,  75,  76,  77,  -1,  78,  -1,
-     -1,  79,  80,  -1,  81,  -1,  -1,  82,  83,  84,
-     85,  86,  87,  -1,  88,  -1,  89,  90,  -1,  91,
-     92,  -1,  93,  94,  -1,  95,  -1,  -1,  96,  97,
-     98,  99,  -1, 100,  -1, 101, 102, 103,  -1, 104,
-    105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
-     -1, 115,  -1, 116,  -1, 117,  -1,  -1, 118, 119,
-     -1,  -1,  -1,  -1,  -1, 120,  -1, 121,  -1, 122,
-    123, 124,  -1,  -1,  -1,  -1,  -1, 125,  -1,  -1,
-     -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 126,  -1,
-     -1, 127, 128,  -1, 129,  -1, 130,  -1,  -1,  -1,
-     -1,  -1,  -1, 131,  -1, 132,  -1, 133, 134,  -1,
-     -1,  -1,  -1, 135,  -1,  -1,  -1,  -1,  -1,  -1,
-    136,  -1,  -1,  -1,  -1,  -1,  -1, 137
+     35,  36,  37,  38,  39,  40,  -1,  41,  -1,  -1,
+     -1,  42,  43,  44,  45,  -1,  46,  -1,  47,  -1,
+     48,  49,  50,  51,  52,  53,  54,  55,  56,  57,
+     58,  59,  -1,  -1,  60,  61,  62,  -1,  63,  -1,
+     64,  -1,  65,  66,  67,  68,  69,  70,  71,  72,
+     -1,  73,  74,  75,  76,  77,  78,  -1,  79,  -1,
+     -1,  80,  81,  -1,  82,  -1,  -1,  83,  84,  85,
+     86,  87,  88,  -1,  89,  -1,  90,  91,  -1,  92,
+     93,  -1,  94,  95,  -1,  96,  -1,  -1,  97,  98,
+     99, 100,  -1, 101,  -1, 102, 103, 104,  -1, 105,
+    106, 107, 108, 109, 110, 111, 112, 113, 114, 115,
+     -1, 116,  -1, 117,  -1, 118,  -1,  -1, 119, 120,
+     -1,  -1,  -1,  -1,  -1, 121,  -1, 122,  -1, 123,
+    124, 125,  -1,  -1,  -1,  -1,  -1, 126,  -1,  -1,
+     -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 127,  -1,
+     -1, 128, 129,  -1, 130,  -1, 131,  -1,  -1,  -1,
+     -1,  -1,  -1, 132,  -1, 133,  -1, 134, 135,  -1,
+     -1,  -1,  -1, 136,  -1,  -1,  -1,  -1,  -1,  -1,
+    137,  -1,  -1,  -1,  -1,  -1,  -1, 138
   };
 
 #ifdef __GNUC__
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index 705a7c1..94af493 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -16,7 +16,10 @@
 #ifndef _KEYWORDS_H_
 #define _KEYWORDS_H_
 
-typedef enum {
+typedef enum kw_token_t kw_token_t;
+typedef struct kw_entry_t kw_entry_t;
+
+enum kw_token_t {
 	/* config setup keywords */
 	KW_CHARONDEBUG,
 	KW_UNIQUEIDS,
@@ -69,6 +72,7 @@ typedef enum {
 	KW_MEDIATED_BY,
 	KW_ME_PEERID,
 	KW_REQID,
+	KW_REPLAY_WINDOW,
 	KW_MARK,
 	KW_MARK_IN,
 	KW_MARK_OUT,
@@ -184,6 +188,11 @@ typedef enum {
 	KW_ALSO,
 	KW_AUTO,
 
-} kw_token_t;
+};
+
+struct kw_entry_t {
+	char *name;
+	kw_token_t token;
+};
 
 #endif /* _KEYWORDS_H_ */
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index ad915bf..ee0bd31 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -69,6 +69,7 @@ mediation,         KW_MEDIATION
 mediated_by,       KW_MEDIATED_BY
 me_peerid,         KW_ME_PEERID
 reqid,             KW_REQID
+replay_window,     KW_REPLAY_WINDOW
 mark,              KW_MARK
 mark_in,           KW_MARK_IN
 mark_out,          KW_MARK_OUT
diff --git a/src/starter/lexer.c b/src/starter/lexer.c
deleted file mode 100644
index f093354..0000000
--- a/src/starter/lexer.c
+++ /dev/null
@@ -1,1992 +0,0 @@
-
-#line 3 "lexer.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types. 
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! C99 */
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif	/* defined (__STDC__) */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart(yyin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k.
- * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
- * Ditto for the __ia64__ case accordingly.
- */
-#define YY_BUF_SIZE 32768
-#else
-#define YY_BUF_SIZE 16384
-#endif /* __ia64__ */
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int yyleng;
-
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    #define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void yyrestart (FILE *input_file  );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
-void yy_delete_buffer (YY_BUFFER_STATE b  );
-void yy_flush_buffer (YY_BUFFER_STATE b  );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void yypop_buffer_state (void );
-
-static void yyensure_buffer_stack (void );
-static void yy_load_buffer_state (void );
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
-
-void *yyalloc (yy_size_t  );
-void *yyrealloc (void *,yy_size_t  );
-void yyfree (void *  );
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-typedef unsigned char YY_CHAR;
-
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int yylineno;
-
-int yylineno = 1;
-
-extern char *yytext;
-#define yytext_ptr yytext
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 14
-#define YY_END_OF_BUFFER 15
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[47] =
-    {   0,
-        0,    0,   15,   11,    2,    4,   13,   11,    3,   11,
-       11,   11,   11,    1,   11,    2,    0,   12,   11,    0,
-        4,    8,   11,   11,   11,   11,    1,   11,   11,   11,
-       11,   11,    7,   11,   11,   11,   11,   11,    6,   11,
-        5,   11,   11,    9,   10,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    4,    5,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        6,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    7,    1,    8,    9,
-
-       10,   11,   12,    1,   13,    1,    1,   14,    1,   15,
-       16,   17,    1,   18,   19,   20,   21,   22,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[23] =
-    {   0,
-        1,    2,    3,    2,    1,    2,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1
-    } ;
-
-static yyconst flex_int16_t yy_base[51] =
-    {   0,
-        0,   69,   70,    0,   67,   72,   64,   21,   72,   19,
-       52,   56,   55,   62,    0,   61,   58,   72,   34,   58,
-       72,    0,   45,   51,   38,   39,   54,   17,   41,   33,
-       34,   39,    0,   30,   33,   36,   27,   25,    0,   17,
-        0,   21,   15,    0,    0,   72,   28,   40,   42,   45
-    } ;
-
-static yyconst flex_int16_t yy_def[51] =
-    {   0,
-       46,    1,   46,   47,   46,   46,   48,   49,   46,   47,
-       47,   47,   47,   46,   47,   46,   48,   46,   49,   50,
-       46,   47,   47,   47,   47,   47,   46,   47,   47,   47,
-       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
-       47,   47,   47,   47,   47,    0,   46,   46,   46,   46
-    } ;
-
-static yyconst flex_int16_t yy_nxt[95] =
-    {   0,
-        4,    5,    6,    7,    8,    9,    4,   10,    4,    4,
-        4,    4,   11,    4,    4,    4,    4,    4,   12,    4,
-        4,   13,   20,   21,   20,   22,   20,   32,   15,   45,
-       44,   33,   43,   42,   23,   20,   21,   20,   41,   20,
-       17,   17,   19,   19,   19,   20,   20,   20,   40,   39,
-       38,   37,   36,   35,   34,   27,   31,   30,   29,   28,
-       21,   18,   16,   27,   26,   25,   24,   18,   16,   46,
-       14,    3,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   46,   46,   46
-
-    } ;
-
-static yyconst flex_int16_t yy_chk[95] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    8,    8,    8,   10,    8,   28,   47,   43,
-       42,   28,   40,   38,   10,   19,   19,   19,   37,   19,
-       48,   48,   49,   49,   49,   50,   50,   50,   36,   35,
-       34,   32,   31,   30,   29,   27,   26,   25,   24,   23,
-       20,   17,   16,   14,   13,   12,   11,    7,    5,    3,
-        2,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   46,   46,   46,   46,   46,   46,   46,   46,   46,
-       46,   46,   46,   46
-
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-extern int yy_flex_debug;
-int yy_flex_debug = 0;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "lexer.l"
-#define YY_NO_INPUT 1
-#line 4 "lexer.l"
-/* FreeS/WAN config file parser (parser.l)
- * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#ifdef HAVE_GLOB_H
-#include <glob.h>
-#endif
-
-#include "parser.h"
-
-#define MAX_INCLUDE_DEPTH  20
-
-extern void yyerror(const char *);
-extern int yylex(void);
-extern int yylex_destroy(void);
-
-static struct {
-	int stack_ptr;
-	YY_BUFFER_STATE stack[MAX_INCLUDE_DEPTH];
-	FILE *file[MAX_INCLUDE_DEPTH];
-	unsigned int line[MAX_INCLUDE_DEPTH];
-	char *filename[MAX_INCLUDE_DEPTH];
-} __parser_y_private;
-
-void _parser_y_error(char *b, int size, const char *s);
-void _parser_y_init (const char *f);
-void _parser_y_fini (void);
-int _parser_y_include (const char *filename);
-
-void _parser_y_error(char *b, int size, const char *s)
-{
-	extern char *yytext; // was: char yytext[];
-
-	snprintf(b, size, "%s:%d: %s [%s]",
-			__parser_y_private.filename[__parser_y_private.stack_ptr],
-			__parser_y_private.line[__parser_y_private.stack_ptr],
-			s, yytext);
-}
-
-void _parser_y_init (const char *f)
-{
-	memset(&__parser_y_private, 0, sizeof(__parser_y_private));
-	__parser_y_private.line[0] = 1;
-	__parser_y_private.filename[0] = strdup(f);
-}
-
-void _parser_y_fini (void)
-{
-	unsigned int i;
-
-	for (i = 0; i < MAX_INCLUDE_DEPTH; i++)
-	{
-		if (__parser_y_private.filename[i])
-			free(__parser_y_private.filename[i]);
-		if (__parser_y_private.file[i])
-			fclose(__parser_y_private.file[i]);
-	}
-	memset(&__parser_y_private, 0, sizeof(__parser_y_private));
-	yylex_destroy();
-}
-
-/**
- * parse the file located at filename
- */
-int include_file(char *filename)
-{
-	unsigned int p = __parser_y_private.stack_ptr + 1;
-	FILE *f;
-
-	if (p >= MAX_INCLUDE_DEPTH)
-	{
-		yyerror("max inclusion depth reached");
-		return 1;
-	}
-
-	f = fopen(filename, "r");
-	if (!f)
-	{
-		yyerror("can't open include filename");
-		return 0; /* ignore this error */
-	}
-
-	__parser_y_private.stack_ptr++;
-	__parser_y_private.file[p] = f;
-	__parser_y_private.stack[p] = YY_CURRENT_BUFFER;
-	__parser_y_private.line[p] = 1;
-	__parser_y_private.filename[p] = strdup(filename);
-
-	yy_switch_to_buffer(yy_create_buffer(f,YY_BUF_SIZE));
-	return 0;
-}
-
-int _parser_y_include (const char *filename)
-{
-	int ret = 0;
-#ifdef HAVE_GLOB_H
-	{
-		glob_t files;
-		int i;
-
-		ret = glob(filename, GLOB_ERR, NULL, &files);
-		if (ret)
-		{
-			const char *err;
-
-			switch (ret)
-			{
-				case GLOB_NOSPACE:
-					err = "include files ran out of memory";
-					break;
-				case GLOB_ABORTED:
-					err = "include files aborted due to read error";
-					break;
-				case GLOB_NOMATCH:
-					err = "include files found no matches";
-					break;
-				default:
-					err = "unknown include files error";
-			}
-			globfree(&files);
-			yyerror(err);
-			return 1;
-		}
-
-		for (i = 0; i < files.gl_pathc; i++)
-		{
-			if ((ret = include_file(files.gl_pathv[i])))
-			{
-				break;
-			}
-		}
-		globfree(&files);
-	}
-#else /* HAVE_GLOB_H */
-	/* if glob(3) is not available, try to load pattern directly */
-	ret = include_file(filename);
-#endif /* HAVE_GLOB_H */
-	return ret;
-}
-
-#line 647 "lexer.c"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Accessor methods to globals.
-   These are made visible to non-reentrant scanners for convenience. */
-
-int yylex_destroy (void );
-
-int yyget_debug (void );
-
-void yyset_debug (int debug_flag  );
-
-YY_EXTRA_TYPE yyget_extra (void );
-
-void yyset_extra (YY_EXTRA_TYPE user_defined  );
-
-FILE *yyget_in (void );
-
-void yyset_in  (FILE * in_str  );
-
-FILE *yyget_out (void );
-
-void yyset_out  (FILE * out_str  );
-
-int yyget_leng (void );
-
-char *yyget_text (void );
-
-int yyget_lineno (void );
-
-void yyset_lineno (int line_number  );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (void );
-#else
-extern int yywrap (void );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#ifdef __ia64__
-/* On IA-64, the buffer size is 16k, not 8k */
-#define YY_READ_BUF_SIZE 16384
-#else
-#define YY_READ_BUF_SIZE 8192
-#endif /* __ia64__ */
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex (void);
-
-#define YY_DECL int yylex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	if ( yyleng > 0 ) \
-		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
-				(yytext[yyleng - 1] == '\n'); \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 159 "lexer.l"
-
-
-#line 838 "lexer.c"
-
-	if ( !(yy_init) )
-		{
-		(yy_init) = 1;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			yyensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				yy_create_buffer(yyin,YY_BUF_SIZE );
-		}
-
-		yy_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of yytext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-		yy_current_state += YY_AT_BOL();
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 47 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_base[yy_current_state] != 72 );
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-		if ( yy_act == 0 )
-			{ /* have to back up */
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			yy_act = yy_accept[yy_current_state];
-			}
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case YY_STATE_EOF(INITIAL):
-#line 161 "lexer.l"
-{
-		if (__parser_y_private.filename[__parser_y_private.stack_ptr]) {
-				free(__parser_y_private.filename[__parser_y_private.stack_ptr]);
-				__parser_y_private.filename[__parser_y_private.stack_ptr] = NULL;
-		}
-		if (__parser_y_private.file[__parser_y_private.stack_ptr]) {
-				fclose(__parser_y_private.file[__parser_y_private.stack_ptr]);
-				__parser_y_private.file[__parser_y_private.stack_ptr] = NULL;
-				yy_delete_buffer (YY_CURRENT_BUFFER);
-				yy_switch_to_buffer
-						(__parser_y_private.stack[__parser_y_private.stack_ptr]);
-		}
-		if (--__parser_y_private.stack_ptr < 0) {
-				yyterminate();
-		}
-}
-	YY_BREAK
-case 1:
-YY_RULE_SETUP
-#line 178 "lexer.l"
-return FIRST_SPACES;
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 180 "lexer.l"
-/* ignore spaces in line */ ;
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 182 "lexer.l"
-return EQUAL;
-	YY_BREAK
-case 4:
-/* rule 4 can match eol */
-YY_RULE_SETUP
-#line 184 "lexer.l"
-{
-										__parser_y_private.line[__parser_y_private.stack_ptr]++;
-										return EOL;
-								}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 189 "lexer.l"
-return CONFIG;
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 190 "lexer.l"
-return SETUP;
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 191 "lexer.l"
-return CONN;
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 192 "lexer.l"
-return CA;
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 193 "lexer.l"
-return INCLUDE;
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 194 "lexer.l"
-return FILE_VERSION;
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 196 "lexer.l"
-{
-										yylval.s = strdup(yytext);
-										return STRING;
-								}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 201 "lexer.l"
-{
-										yylval.s = strdup(yytext+1);
-										if (yylval.s) yylval.s[strlen(yylval.s)-1]='\0';
-										return STRING;
-								}
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 207 "lexer.l"
-yyerror(yytext);
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 209 "lexer.l"
-ECHO;
-	YY_BREAK
-#line 1022 "lexer.c"
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( yywrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			int num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart(yyin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
-		/* Extend the array by 50%, plus the number we really need. */
-		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
-		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
-		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
-	}
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-	yy_current_state += YY_AT_BOL();
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 47 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		(yy_last_accepting_state) = yy_current_state;
-		(yy_last_accepting_cpos) = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 47 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 46);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart(yyin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve yytext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * 
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void yyrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        yyensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            yy_create_buffer(yyin,YY_BUF_SIZE );
-	}
-
-	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
-	yy_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		yypop_buffer_state();
-	 *		yypush_buffer_state(new_buffer);
-     */
-	yyensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	yy_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void yy_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_c_buf_p);
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with yy_create_buffer()
- * 
- */
-    void yy_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yyfree((void *) b->yy_ch_buf  );
-
-	yyfree((void *) b  );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-    
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a yyrestart() or at EOF.
- */
-    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	yy_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then yy_init_buffer was _probably_
-     * called from yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void yy_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		yy_load_buffer_state( );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  
- */
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	yyensure_buffer_stack();
-
-	/* This block is copied from yy_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from yy_switch_to_buffer. */
-	yy_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void yypop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	yy_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		yy_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void yyensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_buffer_stack)) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-								  
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		if ( ! (yy_buffer_stack) )
-			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_buffer_stack_max) = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * 
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- * 
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
-{
-    
-	return yy_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
- * scan from a @e copy of @a bytes.
- * @param yybytes the byte buffer to scan
- * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = _yybytes_len + 2;
-	buf = (char *) yyalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < _yybytes_len; ++i )
-		buf[i] = yybytes[i];
-
-	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = (yy_hold_char); \
-		(yy_c_buf_p) = yytext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int yyget_lineno  (void)
-{
-        
-    return yylineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *yyget_in  (void)
-{
-        return yyin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *yyget_out  (void)
-{
-        return yyout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int yyget_leng  (void)
-{
-        return yyleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *yyget_text  (void)
-{
-        return yytext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void yyset_lineno (int  line_number )
-{
-    
-    yylineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see yy_switch_to_buffer
- */
-void yyset_in (FILE *  in_str )
-{
-        yyin = in_str ;
-}
-
-void yyset_out (FILE *  out_str )
-{
-        yyout = out_str ;
-}
-
-int yyget_debug  (void)
-{
-        return yy_flex_debug;
-}
-
-void yyset_debug (int  bdebug )
-{
-        yy_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
-        /* Initialization is the same as for the non-reentrant scanner.
-     * This function is called from yylex_destroy(), so don't allocate here.
-     */
-
-    (yy_buffer_stack) = 0;
-    (yy_buffer_stack_top) = 0;
-    (yy_buffer_stack_max) = 0;
-    (yy_c_buf_p) = (char *) 0;
-    (yy_init) = 0;
-    (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
-    yyin = stdin;
-    yyout = stdout;
-#else
-    yyin = (FILE *) 0;
-    yyout = (FILE *) 0;
-#endif
-
-    /* For future reference: Set errno on error, since we are called by
-     * yylex_init()
-     */
-    return 0;
-}
-
-/* yylex_destroy is for both reentrant and non-reentrant scanners. */
-int yylex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		yy_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		yypop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	yyfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    /* Reset the globals. This is important in a non-reentrant scanner so the next time
-     * yylex() is called, initialization will occur. */
-    yy_init_globals( );
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *yyalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *yyrealloc  (void * ptr, yy_size_t  size )
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void yyfree (void * ptr )
-{
-	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 209 "lexer.l"
-
-
-
-int yywrap(void)
-{
-	return 1;
-}
-
-
diff --git a/src/starter/lexer.l b/src/starter/lexer.l
deleted file mode 100644
index 734776a..0000000
--- a/src/starter/lexer.l
+++ /dev/null
@@ -1,215 +0,0 @@
-%option noinput
-%option nounput
-%{
-/* FreeS/WAN config file parser (parser.l)
- * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#ifdef HAVE_GLOB_H
-#include <glob.h>
-#endif
-
-#include "parser.h"
-
-#define MAX_INCLUDE_DEPTH  20
-
-extern void yyerror(const char *);
-extern int yylex(void);
-extern int yylex_destroy(void);
-
-static struct {
-	int stack_ptr;
-	YY_BUFFER_STATE stack[MAX_INCLUDE_DEPTH];
-	FILE *file[MAX_INCLUDE_DEPTH];
-	unsigned int line[MAX_INCLUDE_DEPTH];
-	char *filename[MAX_INCLUDE_DEPTH];
-} __parser_y_private;
-
-void _parser_y_error(char *b, int size, const char *s);
-void _parser_y_init (const char *f);
-void _parser_y_fini (void);
-int _parser_y_include (const char *filename);
-
-void _parser_y_error(char *b, int size, const char *s)
-{
-	extern char *yytext; // was: char yytext[];
-
-	snprintf(b, size, "%s:%d: %s [%s]",
-			__parser_y_private.filename[__parser_y_private.stack_ptr],
-			__parser_y_private.line[__parser_y_private.stack_ptr],
-			s, yytext);
-}
-
-void _parser_y_init (const char *f)
-{
-	memset(&__parser_y_private, 0, sizeof(__parser_y_private));
-	__parser_y_private.line[0] = 1;
-	__parser_y_private.filename[0] = strdup(f);
-}
-
-void _parser_y_fini (void)
-{
-	unsigned int i;
-
-	for (i = 0; i < MAX_INCLUDE_DEPTH; i++)
-	{
-		if (__parser_y_private.filename[i])
-			free(__parser_y_private.filename[i]);
-		if (__parser_y_private.file[i])
-			fclose(__parser_y_private.file[i]);
-	}
-	memset(&__parser_y_private, 0, sizeof(__parser_y_private));
-	yylex_destroy();
-}
-
-/**
- * parse the file located at filename
- */
-int include_file(char *filename)
-{
-	unsigned int p = __parser_y_private.stack_ptr + 1;
-	FILE *f;
-
-	if (p >= MAX_INCLUDE_DEPTH)
-	{
-		yyerror("max inclusion depth reached");
-		return 1;
-	}
-
-	f = fopen(filename, "r");
-	if (!f)
-	{
-		yyerror("can't open include filename");
-		return 0; /* ignore this error */
-	}
-
-	__parser_y_private.stack_ptr++;
-	__parser_y_private.file[p] = f;
-	__parser_y_private.stack[p] = YY_CURRENT_BUFFER;
-	__parser_y_private.line[p] = 1;
-	__parser_y_private.filename[p] = strdup(filename);
-
-	yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
-	return 0;
-}
-
-int _parser_y_include (const char *filename)
-{
-	int ret = 0;
-#ifdef HAVE_GLOB_H
-	{
-		glob_t files;
-		int i;
-
-		ret = glob(filename, GLOB_ERR, NULL, &files);
-		if (ret)
-		{
-			const char *err;
-
-			switch (ret)
-			{
-				case GLOB_NOSPACE:
-					err = "include files ran out of memory";
-					break;
-				case GLOB_ABORTED:
-					err = "include files aborted due to read error";
-					break;
-				case GLOB_NOMATCH:
-					err = "include files found no matches";
-					break;
-				default:
-					err = "unknown include files error";
-			}
-			globfree(&files);
-			yyerror(err);
-			return 1;
-		}
-
-		for (i = 0; i < files.gl_pathc; i++)
-		{
-			if ((ret = include_file(files.gl_pathv[i])))
-			{
-				break;
-			}
-		}
-		globfree(&files);
-	}
-#else /* HAVE_GLOB_H */
-	/* if glob(3) is not available, try to load pattern directly */
-	ret = include_file(filename);
-#endif /* HAVE_GLOB_H */
-	return ret;
-}
-
-%}
-
-%%
-
-<<EOF>> {
-		if (__parser_y_private.filename[__parser_y_private.stack_ptr]) {
-				free(__parser_y_private.filename[__parser_y_private.stack_ptr]);
-				__parser_y_private.filename[__parser_y_private.stack_ptr] = NULL;
-		}
-		if (__parser_y_private.file[__parser_y_private.stack_ptr]) {
-				fclose(__parser_y_private.file[__parser_y_private.stack_ptr]);
-				__parser_y_private.file[__parser_y_private.stack_ptr] = NULL;
-				yy_delete_buffer (YY_CURRENT_BUFFER);
-				yy_switch_to_buffer
-						(__parser_y_private.stack[__parser_y_private.stack_ptr]);
-		}
-		if (--__parser_y_private.stack_ptr < 0) {
-				yyterminate();
-		}
-}
-
-^[\t ]+                 return FIRST_SPACES;
-
-[\t ]+                  /* ignore spaces in line */ ;
-
-=                               return EQUAL;
-
-\n|#.*\n                {
-										__parser_y_private.line[__parser_y_private.stack_ptr]++;
-										return EOL;
-								}
-
-config                  return CONFIG;
-setup                   return SETUP;
-conn                    return CONN;
-ca                      return CA;
-include                 return INCLUDE;
-version                 return FILE_VERSION;
-
-[^\"= \t\n]+    {
-										yylval.s = strdup(yytext);
-										return STRING;
-								}
-
-\"[^\"\n]*\"    {
-										yylval.s = strdup(yytext+1);
-										if (yylval.s) yylval.s[strlen(yylval.s)-1]='\0';
-										return STRING;
-								}
-
-.                               yyerror(yytext);
-
-%%
-
-int yywrap(void)
-{
-	return 1;
-}
-
diff --git a/src/starter/parser.c b/src/starter/parser.c
deleted file mode 100644
index 1e6e180..0000000
--- a/src/starter/parser.c
+++ /dev/null
@@ -1,1870 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996.  */
-
-/* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-   
-   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 3 of the License, or
-   (at your option) any later version.
-   
-   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.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
-   simplifying the original so-called "semantic" parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Bison version.  */
-#define YYBISON_VERSION "2.7.12-4996"
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Push parsers.  */
-#define YYPUSH 0
-
-/* Pull parsers.  */
-#define YYPULL 1
-
-
-
-
-/* Copy the first part of user declarations.  */
-/* Line 371 of yacc.c  */
-#line 1 "parser.y"
-
-/* strongSwan config file parser (parser.y)
- * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <library.h>
-#include <utils/debug.h>
-
-#include "ipsec-parser.h"
-
-#define YYERROR_VERBOSE
-#define ERRSTRING_LEN   256
-
-/**
- * Bison
- */
-static char parser_errstring[ERRSTRING_LEN+1];
-
-extern void yyerror(const char *s);
-extern int yylex (void);
-extern void _parser_y_error(char *b, int size, const char *s);
-
-/**
- * Static Globals
- */
-static int _save_errors_;
-static config_parsed_t *_parser_cfg;
-static kw_list_t **_parser_kw, *_parser_kw_last;
-static char errbuf[ERRSTRING_LEN+1];
-
-/**
- * Gperf
- */
-extern kw_entry_t *in_word_set (char *str, unsigned int len);
-
-
-/* Line 371 of yacc.c  */
-#line 119 "parser.c"
-
-# ifndef YY_NULL
-#  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
-#  else
-#   define YY_NULL 0
-#  endif
-# endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* In a future release of Bison, this section will be replaced
-   by #include "y.tab.h".  */
-#ifndef YY_YY_PARSER_H_INCLUDED
-# define YY_YY_PARSER_H_INCLUDED
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     EQUAL = 258,
-     FIRST_SPACES = 259,
-     EOL = 260,
-     CONFIG = 261,
-     SETUP = 262,
-     CONN = 263,
-     CA = 264,
-     INCLUDE = 265,
-     FILE_VERSION = 266,
-     STRING = 267
-   };
-#endif
-/* Tokens.  */
-#define EQUAL 258
-#define FIRST_SPACES 259
-#define EOL 260
-#define CONFIG 261
-#define SETUP 262
-#define CONN 263
-#define CA 264
-#define INCLUDE 265
-#define FILE_VERSION 266
-#define STRING 267
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-/* Line 387 of yacc.c  */
-#line 52 "parser.y"
- char *s; 
-
-/* Line 387 of yacc.c  */
-#line 189 "parser.c"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-extern YYSTYPE yylval;
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_PARSER_H_INCLUDED  */
-
-/* Copy the second part of user declarations.  */
-
-/* Line 390 of yacc.c  */
-#line 217 "parser.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-#  define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-#  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# else
-#  define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-#  if ENABLE_NLS
-#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
-#  endif
-# endif
-# ifndef YY_
-#  define YY_(Msgid) Msgid
-# endif
-#endif
-
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later.  */
-# if (! defined __GNUC__ || __GNUC__ < 2 \
-      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
-#  define __attribute__(Spec) /* empty */
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E.  */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(E) ((void) (E))
-#else
-# define YYUSE(E) /* empty */
-#endif
-
-
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(N) (N)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
-    int yyi;
-#endif
-{
-  return yyi;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   elif defined __BUILTIN_VA_ARG_INCR
-#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-#   elif defined _AIX
-#    define YYSTACK_ALLOC __alloca
-#   elif defined _MSC_VER
-#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-#    define alloca _alloca
-#   else
-#    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-    /* The OS might guarantee only one guard page at the bottom of the stack,
-       and a page size can be as small as 4096 bytes.  So we cannot safely
-       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
-       to allow for a few compiler-allocated temporary stack slots.  */
-#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-#  endif
-# else
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-#  ifndef YYSTACK_ALLOC_MAXIMUM
-#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-#  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
-       && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
-#   endif
-#  endif
-#  ifndef YYMALLOC
-#   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-#  ifndef YYFREE
-#   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-#   endif
-#  endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
-     && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  yytype_int16 yyss_alloc;
-  YYSTYPE yyvs_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
-      + YYSTACK_GAP_MAXIMUM)
-
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from SRC to DST.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(Dst, Src, Count) \
-      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
-#  else
-#   define YYCOPY(Dst, Src, Count)              \
-      do                                        \
-        {                                       \
-          YYSIZE_T yyi;                         \
-          for (yyi = 0; yyi < (Count); yyi++)   \
-            (Dst)[yyi] = (Src)[yyi];            \
-        }                                       \
-      while (YYID (0))
-#  endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
-/* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  2
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   27
-
-/* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  13
-/* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  9
-/* YYNRULES -- Number of rules.  */
-#define YYNRULES  18
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  34
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   267
-
-#define YYTRANSLATE(YYX)						\
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const yytype_uint8 yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint8 yyprhs[] =
-{
-       0,     0,     3,     6,     7,    11,    12,    18,    19,    25,
-      26,    32,    33,    38,    40,    45,    46,    50,    53
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      14,     0,    -1,    14,    15,    -1,    -1,    11,    12,     5,
-      -1,    -1,     6,     7,     5,    16,    20,    -1,    -1,     8,
-      12,     5,    17,    20,    -1,    -1,     9,    12,     5,    18,
-      20,    -1,    -1,    10,    12,    19,     5,    -1,     5,    -1,
-       4,    21,     5,    20,    -1,    -1,    12,     3,    12,    -1,
-      12,     3,    -1,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const yytype_uint8 yyrline[] =
-{
-       0,    63,    63,    64,    68,    73,    72,    78,    77,    94,
-      93,   109,   108,   114,   118,   119,   123,   148,   152
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || 0
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "EQUAL", "FIRST_SPACES", "EOL", "CONFIG",
-  "SETUP", "CONN", "CA", "INCLUDE", "FILE_VERSION", "STRING", "$accept",
-  "config_file", "section_or_include", "$@1", "$@2", "$@3", "$@4",
-  "kw_section", "statement_kw", YY_NULL
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const yytype_uint16 yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    13,    14,    14,    15,    16,    15,    17,    15,    18,
-      15,    19,    15,    15,    20,    20,    21,    21,    21
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     2,     0,     3,     0,     5,     0,     5,     0,
-       5,     0,     4,     1,     4,     0,     3,     2,     0
-};
-
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
-{
-       3,     0,     1,    13,     0,     0,     0,     0,     0,     2,
-       0,     0,     0,    11,     0,     5,     7,     9,     0,     4,
-      15,    15,    15,    12,    18,     6,     8,    10,     0,     0,
-      17,    15,    16,    14
-};
-
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
-{
-      -1,     1,     9,    20,    21,    22,    18,    25,    29
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -20
-static const yytype_int8 yypact[] =
-{
-     -20,     0,   -20,   -20,    -6,    -8,    -5,     1,     2,   -20,
-      10,    11,    12,   -20,    13,   -20,   -20,   -20,    14,   -20,
-      16,    16,    16,   -20,     9,   -20,   -20,   -20,    19,    18,
-      15,    16,   -20,   -20
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int8 yypgoto[] =
-{
-     -20,   -20,   -20,   -20,   -20,   -20,   -20,   -19,   -20
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const yytype_uint8 yytable[] =
-{
-       2,    10,    26,    27,    11,     3,     4,    12,     5,     6,
-       7,     8,    33,    13,    14,    15,    16,    17,    19,    23,
-      24,    28,    30,    31,     0,     0,     0,    32
-};
-
-#define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-20)))
-
-#define yytable_value_is_error(Yytable_value) \
-  YYID (0)
-
-static const yytype_int8 yycheck[] =
-{
-       0,     7,    21,    22,    12,     5,     6,    12,     8,     9,
-      10,    11,    31,    12,    12,     5,     5,     5,     5,     5,
-       4,    12,     3,     5,    -1,    -1,    -1,    12
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const yytype_uint8 yystos[] =
-{
-       0,    14,     0,     5,     6,     8,     9,    10,    11,    15,
-       7,    12,    12,    12,    12,     5,     5,     5,    19,     5,
-      16,    17,    18,     5,     4,    20,    20,    20,    12,    21,
-       3,     5,    12,    20
-};
-
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
-
-#define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)                                  \
-do                                                              \
-  if (yychar == YYEMPTY)                                        \
-    {                                                           \
-      yychar = (Token);                                         \
-      yylval = (Value);                                         \
-      YYPOPSTACK (yylen);                                       \
-      yystate = *yyssp;                                         \
-      goto yybackup;                                            \
-    }                                                           \
-  else                                                          \
-    {                                                           \
-      yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-/* Error token number */
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  FILE *yyo = yyoutput;
-  YYUSE (yyo);
-  if (!yyvaluep)
-    return;
-# ifdef YYPRINT
-  if (yytype < YYNTOKENS)
-    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
-# endif
-  YYUSE (yytype);
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
-{
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
-  YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (; yybottom <= yytop; yybottom++)
-    {
-      int yybot = *yybottom;
-      YYFPRINTF (stderr, " %d", yybot);
-    }
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
-{
-  int yynrhs = yyr2[yyrule];
-  int yyi;
-  unsigned long int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
-  /* The symbols being reduced.  */
-  for (yyi = 0; yyi < yynrhs; yyi++)
-    {
-      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       );
-      YYFPRINTF (stderr, "\n");
-    }
-}
-
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined __GLIBC__ && defined _STRING_H
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
-{
-  YYSIZE_T yylen;
-  for (yylen = 0; yystr[yylen]; yylen++)
-    continue;
-  return yylen;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
-{
-  char *yyd = yydest;
-  const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
-   quotes and backslashes, so that it's suitable for yyerror.  The
-   heuristic is that double-quoting is unnecessary unless the string
-   contains an apostrophe, a comma, or backslash (other than
-   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
-   null, do not copy; instead, return the length of what the result
-   would have been.  */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
-  if (*yystr == '"')
-    {
-      YYSIZE_T yyn = 0;
-      char const *yyp = yystr;
-
-      for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
-    do_not_strip_quotes: ;
-    }
-
-  if (! yyres)
-    return yystrlen (yystr);
-
-  return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
-{
-  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
-                  if (! (yysize <= yysize1
-                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                    return 2;
-                  yysize = yysize1;
-                }
-              }
-        }
-    }
-
-  switch (yycount)
-    {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
-
-  {
-    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
-    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-      return 2;
-    yysize = yysize1;
-  }
-
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
-
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
-}
-#endif /* YYERROR_VERBOSE */
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  YYUSE (yyvaluep);
-
-  if (!yymsg)
-    yymsg = "Deleting";
-  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
-  YYUSE (yytype);
-}
-
-
-
-
-/* The lookahead symbol.  */
-int yychar;
-
-
-#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-# define YY_IGNORE_MAYBE_UNINITIALIZED_END
-#endif
-#ifndef YY_INITIAL_VALUE
-# define YY_INITIAL_VALUE(Value) /* Nothing. */
-#endif
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-    int yystate;
-    /* Number of tokens to shift before error messages enabled.  */
-    int yyerrstatus;
-
-    /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
-
-       Refer to the stacks through separate pointers, to allow yyoverflow
-       to reallocate them elsewhere.  */
-
-    /* The state stack.  */
-    yytype_int16 yyssa[YYINITDEPTH];
-    yytype_int16 *yyss;
-    yytype_int16 *yyssp;
-
-    /* The semantic value stack.  */
-    YYSTYPE yyvsa[YYINITDEPTH];
-    YYSTYPE *yyvs;
-    YYSTYPE *yyvsp;
-
-    YYSIZE_T yystacksize;
-
-  int yyn;
-  int yyresult;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  /* The number of symbols on the RHS of the reduced rule.
-     Keep to zero when no symbol should be popped.  */
-  int yylen = 0;
-
-  yyssp = yyss = yyssa;
-  yyvsp = yyvs = yyvsa;
-  yystacksize = YYINITDEPTH;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY; /* Cause a token to be read.  */
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed.  So pushing a state here evens the stacks.  */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyexhaustedlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
-
-      {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-#  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  if (yystate == YYFINAL)
-    YYACCEPT;
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-  /* Do appropriate processing given the current state.  Read a
-     lookahead token if we need one and don't already have one.  */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-  yyn = yypact[yystate];
-  if (yypact_value_is_default (yyn))
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  /* Shift the lookahead token.  */
-  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
-  /* Discard the shifted token.  */
-  yychar = YYEMPTY;
-
-  yystate = yyn;
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 4:
-/* Line 1787 of yacc.c  */
-#line 69 "parser.y"
-    {
-		free((yyvsp[(2) - (3)].s));
-	}
-    break;
-
-  case 5:
-/* Line 1787 of yacc.c  */
-#line 73 "parser.y"
-    {
-		_parser_kw = &(_parser_cfg->config_setup);
-		_parser_kw_last = NULL;
-	}
-    break;
-
-  case 7:
-/* Line 1787 of yacc.c  */
-#line 78 "parser.y"
-    {
-		section_list_t *section = malloc_thing(section_list_t);
-
-		section->name = strdupnull((yyvsp[(2) - (3)].s));
-		section->kw = NULL;
-		section->next = NULL;
-		_parser_kw = &(section->kw);
-		if (!_parser_cfg->conn_first)
-			_parser_cfg->conn_first = section;
-		if (_parser_cfg->conn_last)
-			_parser_cfg->conn_last->next = section;
-		_parser_cfg->conn_last = section;
-		_parser_kw_last = NULL;
-		free((yyvsp[(2) - (3)].s));
-	}
-    break;
-
-  case 9:
-/* Line 1787 of yacc.c  */
-#line 94 "parser.y"
-    {
-		section_list_t *section = malloc_thing(section_list_t);
-		section->name = strdupnull((yyvsp[(2) - (3)].s));
-		section->kw = NULL;
-		section->next = NULL;
-		_parser_kw = &(section->kw);
-		if (!_parser_cfg->ca_first)
-			_parser_cfg->ca_first = section;
-		if (_parser_cfg->ca_last)
-			_parser_cfg->ca_last->next = section;
-		_parser_cfg->ca_last = section;
-		_parser_kw_last = NULL;
-		free((yyvsp[(2) - (3)].s));
-	}
-    break;
-
-  case 11:
-/* Line 1787 of yacc.c  */
-#line 109 "parser.y"
-    {
-		extern void _parser_y_include (const char *f);
-		_parser_y_include((yyvsp[(2) - (2)].s));
-		free((yyvsp[(2) - (2)].s));
-	}
-    break;
-
-  case 16:
-/* Line 1787 of yacc.c  */
-#line 124 "parser.y"
-    {
-		kw_list_t  *new;
-		kw_entry_t *entry = in_word_set((yyvsp[(1) - (3)].s), strlen((yyvsp[(1) - (3)].s)));
-
-		if (entry == NULL)
-		{
-			snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", (yyvsp[(1) - (3)].s));
-			yyerror(errbuf);
-		}
-		else if (_parser_kw)
-		{
-			new = (kw_list_t *)malloc_thing(kw_list_t);
-			new->entry = entry;
-			new->value = strdupnull((yyvsp[(3) - (3)].s));
-			new->next = NULL;
-			if (_parser_kw_last)
-				_parser_kw_last->next = new;
-			_parser_kw_last = new;
-			if (!*_parser_kw)
-				*_parser_kw = new;
-		}
-		free((yyvsp[(1) - (3)].s));
-		free((yyvsp[(3) - (3)].s));
-	}
-    break;
-
-  case 17:
-/* Line 1787 of yacc.c  */
-#line 149 "parser.y"
-    {
-		free((yyvsp[(1) - (2)].s));
-	  }
-    break;
-
-
-/* Line 1787 of yacc.c  */
-#line 1521 "parser.c"
-      default: break;
-    }
-  /* User semantic actions sometimes alter yychar, and that requires
-     that yytoken be updated with the new translation.  We take the
-     approach of translating immediately before every use of yytoken.
-     One alternative is translating here after every semantic action,
-     but that translation would be missed if the semantic action invokes
-     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
-     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
-     incorrect destructor might then be invoked immediately.  In the
-     case of YYERROR or YYBACKUP, subsequent parser actions might lead
-     to an incorrect destructor call or verbose syntax error message
-     before the lookahead is translated.  */
-  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* Make sure we have latest lookahead translation.  See comments at
-     user semantic actions for why this is necessary.  */
-  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if ! YYERROR_VERBOSE
-      yyerror (YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
-      {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
-      }
-# undef YYSYNTAX_ERROR
-#endif
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
-
-      if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
-      else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval);
-	  yychar = YYEMPTY;
-	}
-    }
-
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-  /* Pacify compilers like GCC when the user code never invokes
-     YYERROR and the label yyerrorlab therefore never appears in user
-     code.  */
-  if (/*CONSTCOND*/ 0)
-     goto yyerrorlab;
-
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYERROR.  */
-  YYPOPSTACK (yylen);
-  yylen = 0;
-  YY_STACK_PRINT (yyss, yyssp);
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (!yypact_value_is_default (yyn))
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-	YYABORT;
-
-
-      yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp);
-      YYPOPSTACK (1);
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
-  *++yyvsp = yylval;
-  YY_IGNORE_MAYBE_UNINITIALIZED_END
-
-
-  /* Shift the error token.  */
-  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#if !defined yyoverflow || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here.  |
-`-------------------------------------------------*/
-yyexhaustedlab:
-  yyerror (YY_("memory exhausted"));
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-  if (yychar != YYEMPTY)
-    {
-      /* Make sure we have latest lookahead translation.  See comments at
-         user semantic actions for why this is necessary.  */
-      yytoken = YYTRANSLATE (yychar);
-      yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval);
-    }
-  /* Do not reclaim the symbols of the rule which action triggered
-     this YYABORT or YYACCEPT.  */
-  YYPOPSTACK (yylen);
-  YY_STACK_PRINT (yyss, yyssp);
-  while (yyssp != yyss)
-    {
-      yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp);
-      YYPOPSTACK (1);
-    }
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
-  if (yymsg != yymsgbuf)
-    YYSTACK_FREE (yymsg);
-#endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
-}
-
-
-/* Line 2050 of yacc.c  */
-#line 155 "parser.y"
-
-
-void yyerror(const char *s)
-{
-	if (_save_errors_)
-		_parser_y_error(parser_errstring, ERRSTRING_LEN, s);
-}
-
-config_parsed_t *parser_load_conf(const char *file)
-{
-	config_parsed_t *cfg = NULL;
-	int err = 0;
-	FILE *f;
-
-	extern void _parser_y_init(const char *f);
-	extern void _parser_y_fini(void);
-	extern FILE *yyin;
-
-	memset(parser_errstring, 0, ERRSTRING_LEN+1);
-
-	cfg = (config_parsed_t *)malloc_thing(config_parsed_t);
-	if (cfg)
-	{
-		memset(cfg, 0, sizeof(config_parsed_t));
-		f = fopen(file, "r");
-		if (f)
-		{
-			yyin = f;
-			_parser_y_init(file);
-			_save_errors_ = 1;
-			_parser_cfg = cfg;
-
-			if (yyparse() !=0 )
-			{
-				if (parser_errstring[0] == '\0')
-				{
-					snprintf(parser_errstring, ERRSTRING_LEN, "Unknown error...");
-				}
-				_save_errors_ = 0;
-				while (yyparse() != 0);
-				err++;
-			}
-			else if (parser_errstring[0] != '\0')
-			{
-				err++;
-			}
-			else
-			{
-				/**
-				 * Config valid
-				 */
-			}
-
-			fclose(f);
-		}
-		else
-		{
-			snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", file);
-			err++;
-		}
-	}
-	else
-	{
-		snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory");
-		err++;
-	}
-
-	if (err)
-	{
-		DBG1(DBG_APP, "%s", parser_errstring);
-
-		if (cfg)
-			parser_free_conf(cfg);
-		cfg = NULL;
-	}
-
-	_parser_y_fini();
-	return cfg;
-}
-
-static void parser_free_kwlist(kw_list_t *list)
-{
-	kw_list_t *elt;
-
-	while (list)
-	{
-		elt = list;
-		list = list->next;
-		free(elt->value);
-		free(elt);
-	}
-}
-
-void parser_free_conf(config_parsed_t *cfg)
-{
-	section_list_t *sec;
-	if (cfg)
-	{
-		parser_free_kwlist(cfg->config_setup);
-		while (cfg->conn_first)
-		{
-			sec = cfg->conn_first;
-			cfg->conn_first = cfg->conn_first->next;
-			free(sec->name);
-			parser_free_kwlist(sec->kw);
-			free(sec);
-		}
-		while (cfg->ca_first)
-		{
-			sec = cfg->ca_first;
-			cfg->ca_first = cfg->ca_first->next;
-			free(sec->name);
-			parser_free_kwlist(sec->kw);
-			free(sec);
-		}
-		free(cfg);
-	}
-}
diff --git a/src/starter/parser.h b/src/starter/parser.h
deleted file mode 100644
index 3344f71..0000000
--- a/src/starter/parser.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.7.12-4996.  */
-
-/* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-   
-   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 3 of the License, or
-   (at your option) any later version.
-   
-   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.
-   
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-   
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-#ifndef YY_YY_PARSER_H_INCLUDED
-# define YY_YY_PARSER_H_INCLUDED
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-#if YYDEBUG
-extern int yydebug;
-#endif
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     EQUAL = 258,
-     FIRST_SPACES = 259,
-     EOL = 260,
-     CONFIG = 261,
-     SETUP = 262,
-     CONN = 263,
-     CA = 264,
-     INCLUDE = 265,
-     FILE_VERSION = 266,
-     STRING = 267
-   };
-#endif
-/* Tokens.  */
-#define EQUAL 258
-#define FIRST_SPACES 259
-#define EOL 260
-#define CONFIG 261
-#define SETUP 262
-#define CONN 263
-#define CA 264
-#define INCLUDE 265
-#define FILE_VERSION 266
-#define STRING 267
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-/* Line 2053 of yacc.c  */
-#line 52 "parser.y"
- char *s; 
-
-/* Line 2053 of yacc.c  */
-#line 84 "parser.h"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-extern YYSTYPE yylval;
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-#endif /* !YY_YY_PARSER_H_INCLUDED  */
diff --git a/src/starter/parser.y b/src/starter/parser.y
deleted file mode 100644
index 2cf0501..0000000
--- a/src/starter/parser.y
+++ /dev/null
@@ -1,272 +0,0 @@
-%{
-/* strongSwan config file parser (parser.y)
- * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <library.h>
-#include <utils/debug.h>
-
-#include "ipsec-parser.h"
-
-#define YYERROR_VERBOSE
-#define ERRSTRING_LEN   256
-
-/**
- * Bison
- */
-static char parser_errstring[ERRSTRING_LEN+1];
-
-extern void yyerror(const char *s);
-extern int yylex (void);
-extern void _parser_y_error(char *b, int size, const char *s);
-
-/**
- * Static Globals
- */
-static int _save_errors_;
-static config_parsed_t *_parser_cfg;
-static kw_list_t **_parser_kw, *_parser_kw_last;
-static char errbuf[ERRSTRING_LEN+1];
-
-/**
- * Gperf
- */
-extern kw_entry_t *in_word_set (char *str, unsigned int len);
-
-%}
-
-%union { char *s; };
-%token EQUAL FIRST_SPACES EOL CONFIG SETUP CONN CA INCLUDE FILE_VERSION
-%token <s> STRING
-
-%%
-
-/*
- * Config file
- */
-
-config_file:
-	config_file section_or_include
-	| /* NULL */
-	;
-
-section_or_include:
-	FILE_VERSION STRING EOL
-	{
-		free($2);
-	}
-	| CONFIG SETUP EOL
-	{
-		_parser_kw = &(_parser_cfg->config_setup);
-		_parser_kw_last = NULL;
-	} kw_section
-	| CONN STRING EOL
-	{
-		section_list_t *section = malloc_thing(section_list_t);
-
-		section->name = strdupnull($2);
-		section->kw = NULL;
-		section->next = NULL;
-		_parser_kw = &(section->kw);
-		if (!_parser_cfg->conn_first)
-			_parser_cfg->conn_first = section;
-		if (_parser_cfg->conn_last)
-			_parser_cfg->conn_last->next = section;
-		_parser_cfg->conn_last = section;
-		_parser_kw_last = NULL;
-		free($2);
-	} kw_section
-	| CA STRING EOL
-	{
-		section_list_t *section = malloc_thing(section_list_t);
-		section->name = strdupnull($2);
-		section->kw = NULL;
-		section->next = NULL;
-		_parser_kw = &(section->kw);
-		if (!_parser_cfg->ca_first)
-			_parser_cfg->ca_first = section;
-		if (_parser_cfg->ca_last)
-			_parser_cfg->ca_last->next = section;
-		_parser_cfg->ca_last = section;
-		_parser_kw_last = NULL;
-		free($2);
-	} kw_section
-	| INCLUDE STRING
-	{
-		extern void _parser_y_include (const char *f);
-		_parser_y_include($2);
-		free($2);
-	} EOL
-	| EOL
-	;
-
-kw_section:
-	FIRST_SPACES statement_kw EOL kw_section
-	|
-	;
-
-statement_kw:
-	STRING EQUAL STRING
-	{
-		kw_list_t  *new;
-		kw_entry_t *entry = in_word_set($1, strlen($1));
-
-		if (entry == NULL)
-		{
-			snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", $1);
-			yyerror(errbuf);
-		}
-		else if (_parser_kw)
-		{
-			new = (kw_list_t *)malloc_thing(kw_list_t);
-			new->entry = entry;
-			new->value = strdupnull($3);
-			new->next = NULL;
-			if (_parser_kw_last)
-				_parser_kw_last->next = new;
-			_parser_kw_last = new;
-			if (!*_parser_kw)
-				*_parser_kw = new;
-		}
-		free($1);
-		free($3);
-	}
-	| STRING EQUAL
-	  {
-		free($1);
-	  }
-	|
-	;
-
-%%
-
-void yyerror(const char *s)
-{
-	if (_save_errors_)
-		_parser_y_error(parser_errstring, ERRSTRING_LEN, s);
-}
-
-config_parsed_t *parser_load_conf(const char *file)
-{
-	config_parsed_t *cfg = NULL;
-	int err = 0;
-	FILE *f;
-
-	extern void _parser_y_init(const char *f);
-	extern void _parser_y_fini(void);
-	extern FILE *yyin;
-
-	memset(parser_errstring, 0, ERRSTRING_LEN+1);
-
-	cfg = (config_parsed_t *)malloc_thing(config_parsed_t);
-	if (cfg)
-	{
-		memset(cfg, 0, sizeof(config_parsed_t));
-		f = fopen(file, "r");
-		if (f)
-		{
-			yyin = f;
-			_parser_y_init(file);
-			_save_errors_ = 1;
-			_parser_cfg = cfg;
-
-			if (yyparse() !=0 )
-			{
-				if (parser_errstring[0] == '\0')
-				{
-					snprintf(parser_errstring, ERRSTRING_LEN, "Unknown error...");
-				}
-				_save_errors_ = 0;
-				while (yyparse() != 0);
-				err++;
-			}
-			else if (parser_errstring[0] != '\0')
-			{
-				err++;
-			}
-			else
-			{
-				/**
-				 * Config valid
-				 */
-			}
-
-			fclose(f);
-		}
-		else
-		{
-			snprintf(parser_errstring, ERRSTRING_LEN, "can't load file '%s'", file);
-			err++;
-		}
-	}
-	else
-	{
-		snprintf(parser_errstring, ERRSTRING_LEN, "can't allocate memory");
-		err++;
-	}
-
-	if (err)
-	{
-		DBG1(DBG_APP, "%s", parser_errstring);
-
-		if (cfg)
-			parser_free_conf(cfg);
-		cfg = NULL;
-	}
-
-	_parser_y_fini();
-	return cfg;
-}
-
-static void parser_free_kwlist(kw_list_t *list)
-{
-	kw_list_t *elt;
-
-	while (list)
-	{
-		elt = list;
-		list = list->next;
-		free(elt->value);
-		free(elt);
-	}
-}
-
-void parser_free_conf(config_parsed_t *cfg)
-{
-	section_list_t *sec;
-	if (cfg)
-	{
-		parser_free_kwlist(cfg->config_setup);
-		while (cfg->conn_first)
-		{
-			sec = cfg->conn_first;
-			cfg->conn_first = cfg->conn_first->next;
-			free(sec->name);
-			parser_free_kwlist(sec->kw);
-			free(sec);
-		}
-		while (cfg->ca_first)
-		{
-			sec = cfg->ca_first;
-			cfg->ca_first = cfg->ca_first->next;
-			free(sec->name);
-			parser_free_kwlist(sec->kw);
-			free(sec);
-		}
-		free(cfg);
-	}
-}
diff --git a/src/starter/parser/conf_parser.c b/src/starter/parser/conf_parser.c
new file mode 100644
index 0000000..6d1c54d
--- /dev/null
+++ b/src/starter/parser/conf_parser.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2013-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 "conf_parser.h"
+
+#include <collections/array.h>
+#include <collections/hashtable.h>
+
+/**
+ * Provided by the generated parser
+ */
+bool conf_parser_parse_file(conf_parser_t *this, char *file);
+
+typedef struct private_conf_parser_t private_conf_parser_t;
+typedef struct section_t section_t;
+
+/**
+ * Private data
+ */
+struct private_conf_parser_t {
+
+	/**
+	 * Public interface
+	 */
+	conf_parser_t public;
+
+	/**
+	 * Path to config file
+	 */
+	char *file;
+
+	/**
+	 * TRUE while parsing the config file
+	 */
+	bool parsing;
+
+	/**
+	 * Hashtable for ca sections, as section_t
+	 */
+	hashtable_t *cas;
+
+	/**
+	 * Hashtable for conn sections, as section_t
+	 */
+	hashtable_t *conns;
+
+	/**
+	 * Array to keep track of the order of conn sections, as section_t
+	 */
+	array_t *conns_order;
+
+	/**
+	 * config setup section
+	 */
+	section_t *config_setup;
+
+	/**
+	 * Pointer to the current section (the one added last) during parsing
+	 */
+	section_t *current_section;
+
+	/**
+	 * Refcount for this parser instance (also used by dictionaries)
+	 */
+	refcount_t ref;
+};
+
+typedef struct {
+	/** Key of the setting */
+	char *key;
+	/** Value of the setting */
+	char *value;
+} setting_t;
+
+int setting_find(const void *a, const void *b)
+{
+	const char *key = a;
+	const setting_t *setting = b;
+	return strcmp(key, setting->key);
+}
+
+int setting_sort(const void *a, const void *b, void *user)
+{
+	const setting_t *sa = a, *sb = b;
+	return strcmp(sa->key, sb->key);
+}
+
+static void setting_destroy(setting_t *this)
+{
+	free(this->key);
+	free(this->value);
+	free(this);
+}
+
+struct section_t {
+	/** Name of the section */
+	char *name;
+	/** Sorted array of settings, as setting_t */
+	array_t *settings;
+	/** Array of also= settings (in reversed order, i.e. most important to least
+	 * important), as setting_t */
+	array_t *also;
+	/** Array of linearized parent objects derived from also= settings, in their
+	 * order of importance (most to least, i.e. %default) as section_t
+	 * NULL if not yet determined */
+	array_t *parents;
+};
+
+static section_t *section_create(char *name)
+{
+	section_t *this;
+
+	INIT(this,
+		.name = name,
+	);
+	return this;
+}
+
+static void section_destroy(section_t *this)
+{
+	array_destroy_function(this->settings, (void*)setting_destroy, NULL);
+	array_destroy_function(this->also, (void*)setting_destroy, NULL);
+	array_destroy(this->parents);
+	free(this->name);
+	free(this);
+}
+
+typedef struct {
+	/** Public interface */
+	dictionary_t public;
+	/** Parser object */
+	private_conf_parser_t *parser;
+	/** Section object */
+	section_t *section;
+} section_dictionary_t;
+
+typedef struct {
+	/** Public interface */
+	enumerator_t public;
+	/** Current settings enumerator */
+	enumerator_t *settings;
+	/** Enumerator into parent list */
+	enumerator_t *parents;
+	/** Hashtable to keep track of already enumerated settings */
+	hashtable_t *seen;
+} dictionary_enumerator_t;
+
+METHOD(enumerator_t, dictionary_enumerate, bool,
+	dictionary_enumerator_t *this, char **key, char **value)
+{
+	setting_t *setting;
+	section_t *parent;
+
+	while (TRUE)
+	{
+		if (this->settings &&
+			this->settings->enumerate(this->settings, &setting))
+		{
+			if (this->seen->get(this->seen, setting->key))
+			{
+				continue;
+			}
+			this->seen->put(this->seen, setting->key, setting->key);
+			if (!setting->value)
+			{
+				continue;
+			}
+			if (key)
+			{
+				*key = setting->key;
+			}
+			if (value)
+			{
+				*value = setting->value;
+			}
+			return TRUE;
+		}
+		DESTROY_IF(this->settings);
+		this->settings = NULL;
+		if (this->parents &&
+			this->parents->enumerate(this->parents, &parent))
+		{
+			if (parent->settings)
+			{
+				this->settings = array_create_enumerator(parent->settings);
+			}
+			continue;
+		}
+		DESTROY_IF(this->parents);
+		this->parents = NULL;
+		break;
+	}
+	return FALSE;
+}
+
+METHOD(enumerator_t, dictionary_enumerator_destroy, void,
+	dictionary_enumerator_t *this)
+{
+	DESTROY_IF(this->settings);
+	DESTROY_IF(this->parents);
+	this->seen->destroy(this->seen);
+	free(this);
+}
+
+METHOD(dictionary_t, dictionary_create_enumerator, enumerator_t*,
+	section_dictionary_t *this)
+{
+	dictionary_enumerator_t *enumerator;
+
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)_dictionary_enumerate,
+			.destroy = _dictionary_enumerator_destroy,
+		},
+		.seen = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8),
+	);
+	if (this->section->settings)
+	{
+		enumerator->settings = array_create_enumerator(this->section->settings);
+	}
+	if (this->section->parents)
+	{
+		enumerator->parents = array_create_enumerator(this->section->parents);
+	}
+	return &enumerator->public;
+}
+
+METHOD(dictionary_t, dictionary_get, void*,
+	section_dictionary_t *this, const void *key)
+{
+	enumerator_t *parents;
+	section_t *section;
+	setting_t *setting;
+	char *value = NULL;
+
+	section = this->section;
+	if (array_bsearch(section->settings, key, setting_find, &setting) != -1)
+	{
+		return setting->value;
+	}
+	parents = array_create_enumerator(section->parents);
+	while (parents->enumerate(parents, &section))
+	{
+		if (array_bsearch(section->settings, key, setting_find, &setting) != -1)
+		{
+			value = setting->value;
+			break;
+		}
+	}
+	parents->destroy(parents);
+	return value;
+}
+
+METHOD(dictionary_t, dictionary_destroy, void,
+	section_dictionary_t *this)
+{
+	this->parser->public.destroy(&this->parser->public);
+	free(this);
+}
+
+static dictionary_t *section_dictionary_create(private_conf_parser_t *parser,
+											   section_t *section)
+{
+	section_dictionary_t *this;
+
+	INIT(this,
+		.public = {
+			.create_enumerator = _dictionary_create_enumerator,
+			.get = _dictionary_get,
+			.destroy = _dictionary_destroy,
+		},
+		.parser = parser,
+		.section = section,
+	);
+
+	ref_get(&parser->ref);
+
+	return &this->public;
+}
+
+static bool conn_filter(void *unused, section_t **section, char **name)
+{
+	if (streq((*section)->name, "%default"))
+	{
+		return FALSE;
+	}
+	*name = (*section)->name;
+	return TRUE;
+}
+
+static bool ca_filter(void *unused, void *key, char **name, section_t **section)
+{
+	if (streq((*section)->name, "%default"))
+	{
+		return FALSE;
+	}
+	*name = (*section)->name;
+	return TRUE;
+}
+
+METHOD(conf_parser_t, get_sections, enumerator_t*,
+	private_conf_parser_t *this, conf_parser_section_t type)
+{
+	switch (type)
+	{
+		case CONF_PARSER_CONN:
+			return enumerator_create_filter(
+						array_create_enumerator(this->conns_order),
+						(void*)conn_filter, NULL, NULL);
+		case CONF_PARSER_CA:
+			return enumerator_create_filter(
+						this->cas->create_enumerator(this->cas),
+						(void*)ca_filter, NULL, NULL);
+		case CONF_PARSER_CONFIG_SETUP:
+		default:
+			return enumerator_create_empty();
+	}
+}
+
+METHOD(conf_parser_t, get_section, dictionary_t*,
+	private_conf_parser_t *this, conf_parser_section_t type, char *name)
+{
+	section_t *section = NULL;
+
+	if (name && streq(name, "%default"))
+	{
+		return NULL;
+	}
+	switch (type)
+	{
+		case CONF_PARSER_CONFIG_SETUP:
+			section = this->config_setup;
+			break;
+		case CONF_PARSER_CONN:
+			section = this->conns->get(this->conns, name);
+			break;
+		case CONF_PARSER_CA:
+			section = this->cas->get(this->cas, name);
+			break;
+		default:
+			break;
+	}
+	return section ? section_dictionary_create(this, section) : NULL;
+}
+
+METHOD(conf_parser_t, add_section, bool,
+	private_conf_parser_t *this, conf_parser_section_t type, char *name)
+{
+	hashtable_t *sections = this->conns;
+	array_t *order = this->conns_order;
+	section_t *section = NULL;
+	bool exists = FALSE;
+
+	if (!this->parsing)
+	{
+		free(name);
+		return exists;
+	}
+	switch (type)
+	{
+		case CONF_PARSER_CONFIG_SETUP:
+			section = this->config_setup;
+			/* we don't expect a name, but just in case */
+			free(name);
+			break;
+		case CONF_PARSER_CA:
+			sections = this->cas;
+			order = NULL;
+			/* fall-through */
+		case CONF_PARSER_CONN:
+			section = sections->get(sections, name);
+			if (!section)
+			{
+				section = section_create(name);
+				sections->put(sections, name, section);
+				if (order)
+				{
+					array_insert(order, ARRAY_TAIL, section);
+				}
+			}
+			else
+			{
+				exists = TRUE;
+				free(name);
+			}
+			break;
+
+	}
+	this->current_section = section;
+	return exists;
+}
+
+METHOD(conf_parser_t, add_setting, void,
+	private_conf_parser_t *this, char *key, char *value)
+{
+	section_t *section = this->current_section;
+	setting_t *setting;
+
+	if (!this->parsing || !this->current_section)
+	{
+		free(key);
+		free(value);
+		return;
+	}
+	if (streq(key, "also"))
+	{
+		if (!value || !strlen(value) || streq(value, "%default"))
+		{	/* we require a name, but all sections inherit from %default */
+			free(key);
+			free(value);
+			return;
+		}
+		INIT(setting,
+			.key = key,
+			.value = value,
+		);
+		array_insert_create(&section->also, ARRAY_HEAD, setting);
+		return;
+	}
+	if (array_bsearch(section->settings, key, setting_find, &setting) == -1)
+	{
+		INIT(setting,
+			.key = key,
+			.value = value,
+		);
+		array_insert_create(&section->settings, ARRAY_TAIL, setting);
+		array_sort(section->settings, setting_sort, NULL);
+	}
+	else
+	{
+		free(setting->value);
+		setting->value = value;
+		free(key);
+	}
+}
+
+/**
+ * Check if the given section is contained in the given array.  The search
+ * starts at the given index.
+ */
+static bool is_contained_in(array_t *arr, section_t *section)
+{
+	section_t *current;
+	int i;
+
+	for (i = 0; i < array_count(arr); i++)
+	{
+		array_get(arr, i, &current);
+		if (streq(section->name, current->name))
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * This algorithm to linearize sections uses a bottom-first depth-first
+ * semantic, with an additional elimination step that removes all but the
+ * last occurrence of each section.
+ *
+ * Consider this configuration:
+ *
+ *   conn A
+ *   conn B
+ *     also=A
+ *   conn C
+ *     also=A
+ *   conn D
+ *     also=C
+ *     also=B
+ *
+ * The linearization would yield D B A C A, which gets reduced to D B C A.
+ *
+ * Ambiguous configurations are handled pragmatically.
+ *
+ * Consider the following configuration:
+ *
+ *   conn A
+ *   conn B
+ *   conn C
+ *     also=A
+ *     also=B
+ *   conn D
+ *     also=B
+ *     also=A
+ *   conn E
+ *     also=C
+ *     also=D
+ *
+ * It is ambiguous because D and C include the same two sections but in
+ * a different order.
+ *
+ * The linearization would yield E D A B C B A which gets reduced to E D C B A.
+ */
+static bool resolve_also_single(hashtable_t *sections,
+							section_t *section, section_t *def, array_t *stack)
+{
+	enumerator_t *enumerator;
+	array_t *parents;
+	section_t *parent, *grandparent;
+	setting_t *also;
+	bool success = TRUE;
+	int i;
+
+	array_insert(stack, ARRAY_HEAD, section);
+	parents = array_create(0, 0);
+	enumerator = array_create_enumerator(section->also);
+	while (enumerator->enumerate(enumerator, &also))
+	{
+		parent = sections->get(sections, also->value);
+		if (!parent || is_contained_in(stack, parent))
+		{
+			if (!parent)
+			{
+				DBG1(DBG_CFG, "section '%s' referenced in section '%s' not "
+					 "found", also->value, section->name);
+			}
+			else
+			{
+				DBG1(DBG_CFG, "section '%s' referenced in section '%s' causes "
+					 "a loop", parent->name, section->name);
+			}
+			array_remove_at(section->also, enumerator);
+			setting_destroy(also);
+			success = FALSE;
+			continue;
+		}
+		if (!parent->parents)
+		{
+			if (!resolve_also_single(sections, parent, def, stack))
+			{
+				success = FALSE;
+				continue;
+			}
+		}
+		/* add the grandparents and the parent to the list */
+		array_insert(parents, ARRAY_TAIL, parent);
+		for (i = 0; i < array_count(parent->parents); i++)
+		{
+			array_get(parent->parents, i, &grandparent);
+			array_insert(parents, ARRAY_TAIL, grandparent);
+		}
+	}
+	enumerator->destroy(enumerator);
+	array_remove(stack, ARRAY_HEAD, NULL);
+
+	if (success && def && !array_count(parents))
+	{
+		array_insert(parents, ARRAY_TAIL, def);
+	}
+
+	while (success && array_remove(parents, ARRAY_HEAD, &parent))
+	{
+		if (!is_contained_in(parents, parent))
+		{	/* last occurrence of this section */
+			array_insert_create(&section->parents, ARRAY_TAIL, parent);
+		}
+	}
+	array_destroy(parents);
+	return success;
+}
+
+/**
+ * Resolve also= statements. The functions returns TRUE if everything is fine,
+ * or FALSE if either a referenced section does not exist, or if the section
+ * inheritance can't be determined properly (e.g. if there are loops or if a
+ * section inherits from multiple sections - perhaps over several levels - in
+ * an ambiguous way).
+ */
+static bool resolve_also(hashtable_t *sections)
+{
+	enumerator_t *enumerator;
+	section_t *def, *section;
+	array_t *stack;
+	bool success = TRUE;
+
+	stack = array_create(0, 0);
+
+	def = sections->get(sections, "%default");
+	if (def)
+	{	/* the default section is the only one with an empty parents list */
+		def->parents = array_create(0, 0);
+	}
+	enumerator = sections->create_enumerator(sections);
+	while (enumerator->enumerate(enumerator, NULL, &section))
+	{
+		if (section->parents)
+		{	/* already determined */
+			continue;
+		}
+		success = resolve_also_single(sections, section, def, stack) && success;
+	}
+	enumerator->destroy(enumerator);
+	array_destroy(stack);
+	return success;
+}
+
+METHOD(conf_parser_t, parse, bool,
+	private_conf_parser_t *this)
+{
+	bool success;
+
+	if (!this->file)
+	{	/* no file, lets assume this is OK */
+		return TRUE;
+	}
+	this->parsing = TRUE;
+	success = conf_parser_parse_file(&this->public, this->file);
+	this->parsing = FALSE;
+	return success && resolve_also(this->conns) && resolve_also(this->cas);
+}
+
+METHOD(conf_parser_t, destroy, void,
+	private_conf_parser_t *this)
+{
+	if (ref_put(&this->ref))
+	{
+		this->cas->destroy_function(this->cas, (void*)section_destroy);
+		this->conns->destroy_function(this->conns, (void*)section_destroy);
+		section_destroy(this->config_setup);
+		array_destroy(this->conns_order);
+		free(this->file);
+		free(this);
+	}
+}
+
+/*
+ * Described in header
+ */
+conf_parser_t *conf_parser_create(const char *file)
+{
+	private_conf_parser_t *this;
+
+	INIT(this,
+		.public = {
+			.parse = _parse,
+			.get_sections = _get_sections,
+			.get_section = _get_section,
+			.add_section = _add_section,
+			.add_setting = _add_setting,
+			.destroy = _destroy,
+		},
+		.file = strdupnull(file),
+		.cas = hashtable_create(hashtable_hash_str,
+								hashtable_equals_str, 8),
+		.conns = hashtable_create(hashtable_hash_str,
+								  hashtable_equals_str, 8),
+		.conns_order = array_create(0, 0),
+		.config_setup = section_create(NULL),
+		.ref = 1,
+	);
+
+	return &this->public;
+}
diff --git a/src/starter/parser/conf_parser.h b/src/starter/parser/conf_parser.h
new file mode 100644
index 0000000..2093820
--- /dev/null
+++ b/src/starter/parser/conf_parser.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2013-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.
+ */
+
+/**
+ * @defgroup starter starter
+ *
+ * @defgroup conf_parser conf_parser
+ * @{ @ingroup starter
+ */
+
+#ifndef CONF_PARSER_H_
+#define CONF_PARSER_H_
+
+#include <library.h>
+#include <collections/dictionary.h>
+
+typedef enum conf_parser_section_t conf_parser_section_t;
+typedef struct conf_parser_t conf_parser_t;
+
+/**
+ * Type of section
+ */
+enum conf_parser_section_t {
+	/**
+	 * config setup
+	 */
+	CONF_PARSER_CONFIG_SETUP,
+
+	/**
+	 * conn _name_
+	 */
+	CONF_PARSER_CONN,
+
+	/**
+	 * ca _name_
+	 */
+	CONF_PARSER_CA,
+};
+
+/**
+ * Parser for ipsec.conf
+ */
+struct conf_parser_t {
+
+	/**
+	 * Parse the config file.
+	 *
+	 * @return		TRUE if config file was parsed successfully
+	 */
+	bool (*parse)(conf_parser_t *this);
+
+	/**
+	 * Get the names of all sections of the given type.
+	 *
+	 * @note Returns an empty enumerator for the config setup section.
+	 *
+	 * @return		enumerator over char*
+	 */
+	enumerator_t *(*get_sections)(conf_parser_t *this,
+								  conf_parser_section_t type);
+
+	/**
+	 * Get the section with the given type and name.
+	 *
+	 * @note The name is ignored for the config setup section.
+	 *
+	 * @return		dictionary with settings
+	 */
+	dictionary_t *(*get_section)(conf_parser_t *this,
+								 conf_parser_section_t type, char *name);
+
+	/**
+	 * Add a section while parsing.
+	 *
+	 * @note This method can only be called while parsing the config file.
+	 *
+	 * @param type	type of section to add
+	 * @param name	name of the section, if applicable (gets adopted)
+	 * @return		TRUE if the section already existed (settings get added)
+	 */
+	bool (*add_section)(conf_parser_t *this, conf_parser_section_t type,
+						char *name);
+
+	/**
+	 * Add a key/value pair to the latest section.
+	 *
+	 * @note This method can only be called while parsing the config file.
+	 *
+	 * @param name	key string (gets adopted)
+	 * @param value	optional value string (gets adopted), if no value is
+	 * 				specified the key is set empty
+	 */
+	void (*add_setting)(conf_parser_t *this, char *key, char *value);
+
+
+	/**
+	 * Destroy a conf_parser_t instance.
+	 */
+	void (*destroy)(conf_parser_t *this);
+};
+
+/**
+ * Create a conf_parser_t instance.
+ *
+ * @param file		ipsec.conf file to parse (gets copied)
+ * @return			conf_parser_t instance
+ */
+conf_parser_t *conf_parser_create(const char *file);
+
+#endif /** CONF_PARSER_H_ @}*/
\ No newline at end of file
diff --git a/src/starter/parser/lexer.c b/src/starter/parser/lexer.c
new file mode 100644
index 0000000..157b89c
--- /dev/null
+++ b/src/starter/parser/lexer.c
@@ -0,0 +1,2737 @@
+#line 2 "parser/lexer.c"
+
+#line 4 "parser/lexer.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+/* %not-for-header */
+
+/* %if-c-only */
+/* %if-not-reentrant */
+/* %endif */
+/* %endif */
+/* %ok-for-header */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* %if-c++-only */
+/* %endif */
+
+/* %if-c-only */
+    
+/* %endif */
+
+/* %if-c-only */
+
+/* %endif */
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+/* %if-c-only */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+/* %endif */
+
+/* %if-tables-serialization */
+/* %endif */
+/* end standard C headers. */
+
+/* %if-c-or-c++ */
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* %endif */
+
+/* %if-c++-only */
+/* %endif */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* %not-for-header */
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+/* %ok-for-header */
+
+/* %not-for-header */
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+/* %ok-for-header */
+
+/* %if-reentrant */
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* %endif */
+
+/* %if-not-reentrant */
+/* %endif */
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE conf_parser_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+/* %if-not-reentrant */
+/* %endif */
+
+/* %if-c-only */
+/* %if-not-reentrant */
+/* %endif */
+/* %endif */
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE conf_parser_lex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+/* %if-c-only */
+	FILE *yy_input_file;
+/* %endif */
+
+/* %if-c++-only */
+/* %endif */
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via conf_parser_restart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
+
+/* %if-not-reentrant */
+/* %endif */
+/* %ok-for-header */
+
+/* %endif */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+/* %if-c-only Standard (non-C++) definition */
+
+/* %if-not-reentrant */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
+
+void conf_parser_restart (FILE *input_file ,yyscan_t yyscanner );
+void conf_parser__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE conf_parser__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void conf_parser__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void conf_parser__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void conf_parser_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void conf_parser_pop_buffer_state (yyscan_t yyscanner );
+
+static void conf_parser_ensure_buffer_stack (yyscan_t yyscanner );
+static void conf_parser__load_buffer_state (yyscan_t yyscanner );
+static void conf_parser__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER conf_parser__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE conf_parser__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE conf_parser__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE conf_parser__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+/* %endif */
+
+void *conf_parser_alloc (yy_size_t ,yyscan_t yyscanner );
+void *conf_parser_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void conf_parser_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer conf_parser__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        conf_parser_ensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            conf_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        conf_parser_ensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            conf_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* %% [1.0] yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here */
+/* Begin user sect3 */
+
+#define conf_parser_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+#define FLEX_DEBUG
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+/* %if-c-only Standard (non-C++) definition */
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* %endif */
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+/* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+/* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
+	yyg->yy_c_buf_p = yy_cp;
+
+/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
+#define YY_NUM_RULES 28
+#define YY_END_OF_BUFFER 29
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[81] =
+    {   0,
+        0,    0,    0,    0,    0,    0,   29,   12,    3,    5,
+       11,    4,    6,   12,   12,    2,   12,   12,   17,   13,
+       14,   15,   27,   19,   18,   20,   12,    3,    4,    4,
+        0,   12,    2,    0,    9,   12,   12,   17,   16,   27,
+       26,   24,   25,   21,   22,   23,   12,    0,   12,   12,
+       12,    0,   12,    8,   12,   12,    0,   12,   12,   12,
+        0,   12,   12,   12,    0,    0,   12,    0,    0,    0,
+       12,    0,    1,   10,   10,    0,    0,    0,    7,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    4,    1,    5,    6,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        7,    1,    1,    8,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    9,    1,    1,    1,    1,   10,   11,   12,   13,
+
+       14,   15,   16,    1,   17,    1,    1,   18,    1,   19,
+       20,   21,    1,   22,   23,   24,   25,   26,    1,    1,
+        1,    1,    1,    1,   27,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[28] =
+    {   0,
+        1,    2,    3,    2,    4,    2,    5,    1,    6,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[92] =
+    {   0,
+        0,   16,   41,   49,    6,    7,  141,    0,   23,  172,
+      172,    0,  172,  134,  120,   30,   20,  120,    0,  172,
+      172,   33,    0,  172,  172,   50,    0,   60,    0,    0,
+        0,  118,   69,  115,    0,  109,  105,    0,  172,    0,
+      172,  172,  172,  172,  172,  172,   76,   71,   16,   69,
+       66,   67,   72,    0,   71,   74,   69,   69,   64,   69,
+       62,   77,   61,   55,   60,   54,   94,   66,   64,   49,
+      100,   46,  172,  172,   74,   24,   16,    5,  172,  172,
+      107,  113,  119,  125,  131,  137,  142,  147,  153,  159,
+      165
+
+    } ;
+
+static yyconst flex_int16_t yy_def[92] =
+    {   0,
+       81,   81,   82,   82,   83,   83,   80,   84,   80,   80,
+       80,   85,   80,   84,   84,   80,   84,   84,   86,   80,
+       80,   80,   87,   80,   80,   88,   84,   80,   85,   85,
+       84,   84,   80,   80,   84,   84,   84,   86,   80,   87,
+       80,   80,   80,   80,   80,   80,   84,   80,   84,   84,
+       84,   80,   84,   84,   84,   84,   80,   84,   84,   84,
+       80,   84,   84,   84,   80,   80,   89,   90,   91,   80,
+       89,   91,   80,   80,   90,   80,   80,   80,   80,    0,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80
+
+    } ;
+
+static yyconst flex_int16_t yy_nxt[200] =
+    {   0,
+       80,    9,   10,    9,   11,   12,   13,   14,   24,   24,
+       25,   25,   80,   80,   26,   26,   15,   16,   10,   16,
+       11,   12,   13,   14,   28,   79,   28,   17,   29,   35,
+       53,   33,   15,   33,   54,   29,   39,   39,   39,   36,
+       78,   18,   20,   20,   20,   21,   20,   77,   73,   22,
+       20,   20,   20,   21,   20,   34,   68,   22,   68,   39,
+       42,   28,   76,   28,   43,   29,   73,   75,   44,   75,
+       33,   45,   33,   46,   29,   75,   70,   75,   69,   67,
+       66,   65,   64,   63,   62,   61,   60,   59,   58,   57,
+       56,   55,   52,   51,   34,   72,   73,   72,   72,   72,
+
+       72,   72,   73,   72,   72,   72,   72,    8,    8,    8,
+        8,    8,    8,   19,   19,   19,   19,   19,   19,   23,
+       23,   23,   23,   23,   23,   27,   50,   49,   48,   47,
+       27,   30,   30,   37,   30,   30,   30,   38,   32,   31,
+       80,   38,   40,   40,   80,   80,   40,   41,   41,   41,
+       41,   41,   41,   71,   71,   71,   71,   71,   71,   74,
+       74,   74,   74,   80,   74,   72,   72,   72,   72,   72,
+       72,    7,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80
+
+    } ;
+
+static yyconst flex_int16_t yy_chk[200] =
+    {   0,
+        0,    1,    1,    1,    1,    1,    1,    1,    5,    6,
+        5,    6,    0,    0,    5,    6,    1,    2,    2,    2,
+        2,    2,    2,    2,    9,   78,    9,    2,    9,   17,
+       49,   16,    2,   16,   49,   16,   22,   22,   22,   17,
+       77,    2,    3,    3,    3,    3,    3,   76,   72,    3,
+        4,    4,    4,    4,    4,   16,   64,    4,   64,   22,
+       26,   28,   70,   28,   26,   28,   69,   68,   26,   68,
+       33,   26,   33,   26,   33,   75,   66,   75,   65,   63,
+       62,   61,   60,   59,   58,   57,   56,   55,   53,   52,
+       51,   50,   48,   47,   33,   67,   67,   67,   67,   67,
+
+       67,   71,   71,   71,   71,   71,   71,   81,   81,   81,
+       81,   81,   81,   82,   82,   82,   82,   82,   82,   83,
+       83,   83,   83,   83,   83,   84,   37,   36,   34,   32,
+       84,   85,   85,   18,   85,   85,   85,   86,   15,   14,
+        7,   86,   87,   87,    0,    0,   87,   88,   88,   88,
+       88,   88,   88,   89,   89,   89,   89,   89,   89,   90,
+       90,   90,   90,    0,   90,   91,   91,   91,   91,   91,
+       91,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80
+
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[29] =
+    {   0,
+0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 
+    1, 0, 0, 0, 0, 0, 1, 0, 0,     };
+
+static yyconst flex_int16_t yy_rule_linenum[28] =
+    {   0,
+       60,   61,   62,   63,   65,   67,   68,   69,   70,   72,
+       77,   82,   90,  109,  112,  115,  118,  124,  126,  127,
+      150,  151,  152,  153,  154,  155,  158
+    } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "parser/lexer.l"
+#line 2 "parser/lexer.l"
+/*
+ * Copyright (C) 2013-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 <utils/parser_helper.h>
+#include <parser/conf_parser.h>
+
+#include "parser.h"
+
+bool conf_parser_open_next_file(parser_helper_t *ctx);
+
+static void include_files(parser_helper_t *ctx);
+
+/* use start conditions stack */
+/* do not declare unneded functions */
+#define YY_NO_INPUT 1
+/* don't use global variables, and interact properly with bison */
+/* maintain the line number */
+/* don't generate a default rule */
+/* prefix function/variable declarations */
+/* don't change the name of the output file otherwise autotools has issues */
+/* type of our extra data */
+/* state used to scan include file patterns */
+
+/* state used to scan quoted strings */
+
+#line 661 "parser/lexer.c"
+
+#define INITIAL 0
+#define inc 1
+#define str 2
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+/* %if-c-only */
+#include <unistd.h>
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+#endif
+
+#define YY_EXTRA_TYPE parser_helper_t*
+
+/* %if-c-only Reentrant structure and macros (non-C++). */
+/* %if-reentrant */
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    }; /* end struct yyguts_t */
+
+/* %if-c-only */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+/* %endif */
+
+/* %if-reentrant */
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+int conf_parser_lex_init (yyscan_t* scanner);
+
+int conf_parser_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* %endif */
+
+/* %endif End reentrant structures and macros. */
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int conf_parser_lex_destroy (yyscan_t yyscanner );
+
+int conf_parser_get_debug (yyscan_t yyscanner );
+
+void conf_parser_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE conf_parser_get_extra (yyscan_t yyscanner );
+
+void conf_parser_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *conf_parser_get_in (yyscan_t yyscanner );
+
+void conf_parser_set_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *conf_parser_get_out (yyscan_t yyscanner );
+
+void conf_parser_set_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int conf_parser_get_leng (yyscan_t yyscanner );
+
+char *conf_parser_get_text (yyscan_t yyscanner );
+
+int conf_parser_get_lineno (yyscan_t yyscanner );
+
+void conf_parser_set_lineno (int line_number ,yyscan_t yyscanner );
+
+/* %if-bison-bridge */
+
+YYSTYPE * conf_parser_get_lval (yyscan_t yyscanner );
+
+void conf_parser_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* %endif */
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int conf_parser_wrap (yyscan_t yyscanner );
+#else
+extern int conf_parser_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+/* %not-for-header */
+
+    static void yyunput (int c,char *buf_ptr  ,yyscan_t yyscanner);
+    
+/* %ok-for-header */
+
+/* %endif */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+/* %if-c-only Standard (non-C++) definition */
+/* %not-for-header */
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+/* %ok-for-header */
+
+/* %endif */
+#endif
+
+/* %if-c-only */
+
+    static void yy_push_state (int new_state ,yyscan_t yyscanner);
+    
+    static void yy_pop_state (yyscan_t yyscanner );
+    
+    static int yy_top_state (yyscan_t yyscanner );
+    
+/* %endif */
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* %if-c-only Standard (non-C++) definition */
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+/* %endif */
+/* %if-c++-only C++ definition */
+/* %endif */
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+/* %if-c++-only C++ definition \ */\
+/* %endif */
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+/* %if-c-only */
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+#endif
+
+/* %if-tables-serialization structures and prototypes */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %not-for-header */
+
+/* %tables-yydmap generated elements */
+/* %endif */
+/* end tables serialization structures and prototypes */
+
+/* %ok-for-header */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+/* %if-c-only Standard (non-C++) definition */
+
+extern int conf_parser_lex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int conf_parser_lex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only C++ definition */
+/* %endif */
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+/* %% [6.0] YY_RULE_SETUP definition goes here */
+#define YY_RULE_SETUP \
+	if ( yyleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(yytext[yyleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/* %not-for-header */
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+/* %% [7.0] user's declarations go here */
+#line 58 "parser/lexer.l"
+
+
+#line 976 "parser/lexer.c"
+
+    yylval = yylval_param;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+/* %if-c-only */
+			yyin = stdin;
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+		if ( ! yyout )
+/* %if-c-only */
+			yyout = stdout;
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			conf_parser_ensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				conf_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		conf_parser__load_buffer_state(yyscanner );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+/* %% [8.0] yymore()-related code goes here */
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+/* %% [9.0] code to set up and find next match goes here */
+		yy_current_state = yyg->yy_start;
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 81 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 172 );
+
+yy_find_action:
+/* %% [10.0] code to find the action number goes here */
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+/* %% [11.0] code for yylineno update goes here */
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+/* %% [12.0] debug code goes here */
+		if ( yy_flex_debug )
+			{
+			if ( yy_act == 0 )
+				fprintf( stderr, "--scanner backing up\n" );
+			else if ( yy_act < 28 )
+				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
+				         (long)yy_rule_linenum[yy_act], yytext );
+			else if ( yy_act == 28 )
+				fprintf( stderr, "--accepting default rule (\"%s\")\n",
+				         yytext );
+			else if ( yy_act == 29 )
+				fprintf( stderr, "--(end of buffer or a NUL)\n" );
+			else
+				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
+			}
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+/* %% [13.0] actions go here */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 60 "parser/lexer.l"
+/* eat legacy version delcaration */
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 61 "parser/lexer.l"
+return SPACES;
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 62 "parser/lexer.l"
+/* eat other whitespace */
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 63 "parser/lexer.l"
+/* eat comments */
+	YY_BREAK
+case 5:
+/* rule 5 can match eol */
+YY_RULE_SETUP
+#line 65 "parser/lexer.l"
+return NEWLINE;
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 67 "parser/lexer.l"
+return EQ;
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 68 "parser/lexer.l"
+return CONFIG_SETUP;
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 69 "parser/lexer.l"
+return CONN;
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 70 "parser/lexer.l"
+return CA;
+	YY_BREAK
+case 10:
+/* rule 10 can match eol */
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 72 "parser/lexer.l"
+{
+	yyextra->string_init(yyextra);
+	yy_push_state(inc, yyscanner);
+}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 77 "parser/lexer.l"
+{
+	yyextra->string_init(yyextra);
+	yy_push_state(str, yyscanner);
+}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 82 "parser/lexer.l"
+{
+	yylval->s = strdup(yytext);
+	return STRING;
+}
+	YY_BREAK
+
+/* we allow all characters except # and spaces, they can be escaped */
+case YY_STATE_EOF(inc):
+#line 89 "parser/lexer.l"
+case 13:
+/* rule 13 can match eol */
+YY_RULE_SETUP
+#line 90 "parser/lexer.l"
+{
+		if (*yytext)
+		{
+			switch (yytext[0])
+			{
+				case '\n':
+					/* put the newline back to fix the line numbers */
+					unput('\n');
+					yy_set_bol(0);
+					break;
+				case '#':
+					/* comments are parsed outside of this start condition */
+					unput(yytext[0]);
+					break;
+			}
+		}
+		include_files(yyextra);
+		yy_pop_state(yyscanner);
+	}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 109 "parser/lexer.l"
+{	/* string include */
+		yy_push_state(str, yyscanner);
+	}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 112 "parser/lexer.l"
+{
+		yyextra->string_add(yyextra, yytext);
+	}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 115 "parser/lexer.l"
+{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 118 "parser/lexer.l"
+{
+		yyextra->string_add(yyextra, yytext);
+	}
+	YY_BREAK
+
+
+case 18:
+#line 125 "parser/lexer.l"
+case YY_STATE_EOF(str):
+#line 125 "parser/lexer.l"
+case 19:
+/* rule 19 can match eol */
+#line 127 "parser/lexer.l"
+case 20:
+/* rule 20 can match eol */
+YY_RULE_SETUP
+#line 127 "parser/lexer.l"
+{
+		if (!streq(yytext, "\""))
+		{
+			if (streq(yytext, "\n"))
+			{	/* put the newline back to fix the line numbers */
+				unput('\n');
+				yy_set_bol(0);
+			}
+			PARSER_DBG1(yyextra, "unterminated string detected");
+		}
+		if (yy_top_state(yyscanner) == inc)
+		{	/* string include */
+			include_files(yyextra);
+			yy_pop_state(yyscanner);
+			yy_pop_state(yyscanner);
+		}
+		else
+		{
+			yy_pop_state(yyscanner);
+			yylval->s = yyextra->string_get(yyextra);
+			return STRING;
+		}
+	}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 150 "parser/lexer.l"
+yyextra->string_add(yyextra, "\n");
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 151 "parser/lexer.l"
+yyextra->string_add(yyextra, "\r");
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 152 "parser/lexer.l"
+yyextra->string_add(yyextra, "\t");
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 153 "parser/lexer.l"
+yyextra->string_add(yyextra, "\b");
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 154 "parser/lexer.l"
+yyextra->string_add(yyextra, "\f");
+	YY_BREAK
+case 26:
+/* rule 26 can match eol */
+YY_RULE_SETUP
+#line 155 "parser/lexer.l"
+{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 158 "parser/lexer.l"
+{
+		yyextra->string_add(yyextra, yytext);
+	}
+	YY_BREAK
+
+case YY_STATE_EOF(INITIAL):
+#line 163 "parser/lexer.l"
+{
+	conf_parser_pop_buffer_state(yyscanner);
+	if (!conf_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
+	{
+		yyterminate();
+	}
+}
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 171 "parser/lexer.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+	YY_BREAK
+#line 1331 "parser/lexer.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * conf_parser_lex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */
+				yy_cp = yyg->yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( conf_parser_wrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of conf_parser_lex */
+/* %ok-for-header */
+
+/* %if-c++-only */
+/* %not-for-header */
+
+/* %ok-for-header */
+
+/* %endif */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+/* %if-c-only */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = yyg->yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					conf_parser_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			yyg->yy_n_chars, (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			conf_parser_restart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) conf_parser_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+/* %if-c-only */
+/* %not-for-header */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+/* %% [15.0] code to get the start state into yy_current_state goes here */
+	yy_current_state = yyg->yy_start;
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+/* %% [16.0] code to find the next state goes here */
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 81 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+/* %if-c-only */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+/* %% [17.0] code to find the next state, and perhaps do backing up, goes here */
+	register char *yy_cp = yyg->yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 81 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 80);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+/* %if-c-only */
+
+    static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yy_cp = yyg->yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yyg->yy_hold_char;
+
+	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yyg->yy_n_chars + 2;
+		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+		register char *source =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+/* %% [18.0] update yylineno here */
+
+    if ( c == '\n' ){
+        --yylineno;
+    }
+
+	yyg->yytext_ptr = yy_bp;
+	yyg->yy_hold_char = *yy_cp;
+	yyg->yy_c_buf_p = yy_cp;
+}
+/* %if-c-only */
+
+/* %endif */
+
+/* %if-c-only */
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					conf_parser_restart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( conf_parser_wrap(yyscanner ) )
+						return EOF;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+/* %% [19.0] update BOL and yylineno */
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol )
+		   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+/* %if-c-only */
+#endif	/* ifndef YY_NO_INPUT */
+/* %endif */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+/* %if-c-only */
+    void conf_parser_restart  (FILE * input_file , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        conf_parser_ensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            conf_parser__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	conf_parser__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	conf_parser__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+    void conf_parser__switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		conf_parser_pop_buffer_state();
+	 *		conf_parser_push_buffer_state(new_buffer);
+     */
+	conf_parser_ensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	conf_parser__load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (conf_parser_wrap()) processing, but the only time this flag
+	 * is looked at is after conf_parser_wrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/* %if-c-only */
+static void conf_parser__load_buffer_state  (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+/* %if-c-only */
+    YY_BUFFER_STATE conf_parser__create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) conf_parser_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in conf_parser__create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) conf_parser_alloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in conf_parser__create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	conf_parser__init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with conf_parser__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+    void conf_parser__delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		conf_parser_free((void *) b->yy_ch_buf ,yyscanner );
+
+	conf_parser_free((void *) b ,yyscanner );
+}
+
+/* %if-c-only */
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* %endif */
+
+/* %if-c++-only */
+/* %endif */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a conf_parser_restart() or at EOF.
+ */
+/* %if-c-only */
+    static void conf_parser__init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	conf_parser__flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then conf_parser__init_buffer was _probably_
+     * called from conf_parser_restart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+/* %if-c-only */
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+    void conf_parser__flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		conf_parser__load_buffer_state(yyscanner );
+}
+
+/* %if-c-or-c++ */
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+void conf_parser_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	conf_parser_ensure_buffer_stack(yyscanner);
+
+	/* This block is copied from conf_parser__switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from conf_parser__switch_to_buffer. */
+	conf_parser__load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+/* %if-c-only */
+void conf_parser_pop_buffer_state (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	conf_parser__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		conf_parser__load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+/* %endif */
+
+/* %if-c-or-c++ */
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+/* %if-c-only */
+static void conf_parser_ensure_buffer_stack (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+	int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)conf_parser_alloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in conf_parser_ensure_buffer_stack()" );
+								  
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)conf_parser_realloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in conf_parser_ensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE conf_parser__scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) conf_parser_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in conf_parser__scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	conf_parser__switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan a string. The next call to conf_parser_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       conf_parser__scan_bytes() instead.
+ */
+YY_BUFFER_STATE conf_parser__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+	return conf_parser__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+/* %endif */
+
+/* %if-c-only */
+/** Setup the input buffer state to scan the given bytes. The next call to conf_parser_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE conf_parser__scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) conf_parser_alloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in conf_parser__scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = conf_parser__scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in conf_parser__scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+/* %endif */
+
+/* %if-c-only */
+    static void yy_push_state (int  new_state , yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( yyg->yy_start_stack_ptr >= yyg->yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yyg->yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yyg->yy_start_stack_depth * sizeof( int );
+
+		if ( ! yyg->yy_start_stack )
+			yyg->yy_start_stack = (int *) conf_parser_alloc(new_size ,yyscanner );
+
+		else
+			yyg->yy_start_stack = (int *) conf_parser_realloc((void *) yyg->yy_start_stack,new_size ,yyscanner );
+
+		if ( ! yyg->yy_start_stack )
+			YY_FATAL_ERROR( "out of memory expanding start-condition stack" );
+		}
+
+	yyg->yy_start_stack[yyg->yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+}
+
+/* %if-c-only */
+    static void yy_pop_state  (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( --yyg->yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yyg->yy_start_stack[yyg->yy_start_stack_ptr]);
+}
+
+/* %if-c-only */
+    static int yy_top_state  (yyscan_t yyscanner)
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	return yyg->yy_start_stack[yyg->yy_start_stack_ptr - 1];
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+/* %if-c-only */
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+/* %endif */
+/* %if-c++-only */
+/* %endif */
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/* %if-c-only */
+/* %if-reentrant */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE conf_parser_get_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/* %endif */
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int conf_parser_get_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int conf_parser_get_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *conf_parser_get_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *conf_parser_get_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int conf_parser_get_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *conf_parser_get_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/* %if-reentrant */
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void conf_parser_set_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/* %endif */
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void conf_parser_set_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "conf_parser_set_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void conf_parser_set_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "conf_parser_set_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see conf_parser__switch_to_buffer
+ */
+void conf_parser_set_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void conf_parser_set_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int conf_parser_get_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void conf_parser_set_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* %endif */
+
+/* %if-reentrant */
+/* Accessor methods for yylval and yylloc */
+
+/* %if-bison-bridge */
+
+YYSTYPE * conf_parser_get_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void conf_parser_set_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+/* %endif */
+
+/* User-visible API */
+
+/* conf_parser_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int conf_parser_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) conf_parser_alloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* conf_parser_lex_init_extra has the same functionality as conf_parser_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to conf_parser_alloc in
+ * the yyextra field.
+ */
+
+int conf_parser_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    conf_parser_set_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) conf_parser_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    conf_parser_set_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* %endif if-c-only */
+
+/* %if-c-only */
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from conf_parser_lex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * conf_parser_lex_init()
+     */
+    return 0;
+}
+/* %endif */
+
+/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */
+/* conf_parser_lex_destroy is for both reentrant and non-reentrant scanners. */
+int conf_parser_lex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		conf_parser__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		conf_parser_pop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	conf_parser_free(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        conf_parser_free(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * conf_parser_lex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+/* %if-reentrant */
+    /* Destroy the main struct (reentrant only). */
+    conf_parser_free ( yyscanner , yyscanner );
+    yyscanner = NULL;
+/* %endif */
+    return 0;
+}
+/* %endif */
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *conf_parser_alloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	return (void *) malloc( size );
+}
+
+void *conf_parser_realloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void conf_parser_free (void * ptr , yyscan_t yyscanner)
+{
+	free( (char *) ptr );	/* see conf_parser_realloc() for (char *) cast */
+}
+
+/* %if-tables-serialization definitions */
+/* %define-yytables   The name for this specific scanner's tables. */
+#define YYTABLES_NAME "yytables"
+/* %endif */
+
+/* %ok-for-header */
+
+#line 171 "parser/lexer.l"
+
+
+
+/**
+ * Open the next file, if any is queued and readable, otherwise returns FALSE.
+ */
+bool conf_parser_open_next_file(parser_helper_t *ctx)
+{
+	FILE *file;
+
+	file = ctx->file_next(ctx);
+	if (!file)
+	{
+		return FALSE;
+	}
+
+	conf_parser_set_in(file, ctx->scanner);
+	conf_parser_push_buffer_state(
+			conf_parser__create_buffer(file, YY_BUF_SIZE,
+									   ctx->scanner), ctx->scanner);
+	return TRUE;
+}
+
+/**
+ * Assumes that the file pattern to include is currently stored as string on
+ * the helper object.
+ */
+static void include_files(parser_helper_t *ctx)
+{
+	char *pattern = ctx->string_get(ctx);
+
+	ctx->file_include(ctx, pattern);
+	free(pattern);
+
+	conf_parser_open_next_file(ctx);
+}
+
diff --git a/src/starter/parser/lexer.l b/src/starter/parser/lexer.l
new file mode 100644
index 0000000..a88cbe8
--- /dev/null
+++ b/src/starter/parser/lexer.l
@@ -0,0 +1,205 @@
+%{
+/*
+ * Copyright (C) 2013-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 <utils/parser_helper.h>
+#include <parser/conf_parser.h>
+
+#include "parser.h"
+
+bool conf_parser_open_next_file(parser_helper_t *ctx);
+
+static void include_files(parser_helper_t *ctx);
+
+%}
+%option debug
+%option warn
+
+/* use start conditions stack */
+%option stack
+
+/* do not declare unneded functions */
+%option noinput noyywrap
+
+/* don't use global variables, and interact properly with bison */
+%option reentrant bison-bridge
+
+/* maintain the line number */
+%option yylineno
+
+/* don't generate a default rule */
+%option nodefault
+
+/* prefix function/variable declarations */
+%option prefix="conf_parser_"
+/* don't change the name of the output file otherwise autotools has issues */
+%option outfile="lex.yy.c"
+
+/* type of our extra data */
+%option extra-type="parser_helper_t*"
+
+/* state used to scan include file patterns */
+%x inc
+/* state used to scan quoted strings */
+%x str
+
+%%
+
+^[\t ]*"version"[^\n]*$	/* eat legacy version delcaration */
+^[\t ]+					return SPACES;
+[\t ]+					/* eat other whitespace */
+[\t ]*#[^\n]*			/* eat comments */
+
+\n						return NEWLINE;
+
+"="						return EQ;
+^"config setup"			return CONFIG_SETUP;
+^"conn"					return CONN;
+^"ca"					return CA;
+
+"include"[\t ]+/[^=]	{
+	yyextra->string_init(yyextra);
+	yy_push_state(inc, yyscanner);
+}
+
+"\""					{
+	yyextra->string_init(yyextra);
+	yy_push_state(str, yyscanner);
+}
+
+(@#)?[^\"#= \t\n]+			{
+	yylval->s = strdup(yytext);
+	return STRING;
+}
+
+<inc>{
+	/* we allow all characters except # and spaces, they can be escaped */
+	<<EOF>>				|
+	[#\n\t ]			{
+		if (*yytext)
+		{
+			switch (yytext[0])
+			{
+				case '\n':
+					/* put the newline back to fix the line numbers */
+					unput('\n');
+					yy_set_bol(0);
+					break;
+				case '#':
+					/* comments are parsed outside of this start condition */
+					unput(yytext[0]);
+					break;
+			}
+		}
+		include_files(yyextra);
+		yy_pop_state(yyscanner);
+	}
+	"\""				{	/* string include */
+		yy_push_state(str, yyscanner);
+	}
+	\\					{
+		yyextra->string_add(yyextra, yytext);
+	}
+	\\["#} ]			{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	[^"\\#\n\t ]+ {
+		yyextra->string_add(yyextra, yytext);
+	}
+}
+
+<str>{
+	"\""				|
+	<<EOF>>				|
+	\n					|
+	\\					{
+		if (!streq(yytext, "\""))
+		{
+			if (streq(yytext, "\n"))
+			{	/* put the newline back to fix the line numbers */
+				unput('\n');
+				yy_set_bol(0);
+			}
+			PARSER_DBG1(yyextra, "unterminated string detected");
+		}
+		if (yy_top_state(yyscanner) == inc)
+		{	/* string include */
+			include_files(yyextra);
+			yy_pop_state(yyscanner);
+			yy_pop_state(yyscanner);
+		}
+		else
+		{
+			yy_pop_state(yyscanner);
+			yylval->s = yyextra->string_get(yyextra);
+			return STRING;
+		}
+	}
+	\\n     yyextra->string_add(yyextra, "\n");
+	\\r     yyextra->string_add(yyextra, "\r");
+	\\t     yyextra->string_add(yyextra, "\t");
+	\\b     yyextra->string_add(yyextra, "\b");
+	\\f     yyextra->string_add(yyextra, "\f");
+	\\(.|\n)			{
+		yyextra->string_add(yyextra, yytext+1);
+	}
+	[^\\\n"]+			{
+		yyextra->string_add(yyextra, yytext);
+	}
+}
+
+<<EOF>>					{
+	conf_parser_pop_buffer_state(yyscanner);
+	if (!conf_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
+	{
+		yyterminate();
+	}
+}
+
+%%
+
+/**
+ * Open the next file, if any is queued and readable, otherwise returns FALSE.
+ */
+bool conf_parser_open_next_file(parser_helper_t *ctx)
+{
+	FILE *file;
+
+	file = ctx->file_next(ctx);
+	if (!file)
+	{
+		return FALSE;
+	}
+
+	conf_parser_set_in(file, ctx->scanner);
+	conf_parser_push_buffer_state(
+			conf_parser__create_buffer(file, YY_BUF_SIZE,
+									   ctx->scanner), ctx->scanner);
+	return TRUE;
+}
+
+/**
+ * Assumes that the file pattern to include is currently stored as string on
+ * the helper object.
+ */
+static void include_files(parser_helper_t *ctx)
+{
+	char *pattern = ctx->string_get(ctx);
+
+	ctx->file_include(ctx, pattern);
+	free(pattern);
+
+	conf_parser_open_next_file(ctx);
+}
diff --git a/src/starter/parser/parser.c b/src/starter/parser/parser.c
new file mode 100644
index 0000000..8cf3fe1
--- /dev/null
+++ b/src/starter/parser/parser.c
@@ -0,0 +1,1700 @@
+/* A Bison parser, made by GNU Bison 3.0.2.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.2"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names.  */
+#define yyparse         conf_parser_parse
+#define yylex           conf_parser_lex
+#define yyerror         conf_parser_error
+#define yydebug         conf_parser_debug
+#define yynerrs         conf_parser_nerrs
+
+
+/* Copy the first part of user declarations.  */
+#line 1 "parser/parser.y" /* yacc.c:339  */
+
+/*
+ * Copyright (C) 2013-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.
+ */
+
+#define _GNU_SOURCE /* for asprintf() */
+#include <stdio.h>
+
+#include <utils/parser_helper.h>
+#include <settings/settings_types.h>
+#include <parser/conf_parser.h>
+
+#include "parser.h"
+
+#define YYDEBUG 1
+
+/**
+ * Defined by the lexer
+ */
+int conf_parser_lex(YYSTYPE *lvalp, void *scanner);
+int conf_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
+int conf_parser_lex_destroy(void *scanner);
+int conf_parser_set_in(FILE *in, void *scanner);
+void conf_parser_set_debug(int debug, void *scanner);
+char *conf_parser_get_text(void *scanner);
+int conf_parser_get_leng(void *scanner);
+int conf_parser_get_lineno(void *scanner);
+/* Custom functions in lexer */
+bool conf_parser_open_next_file(parser_helper_t *ctx);
+
+/**
+ * Forward declaration
+ */
+static void conf_parser_error(parser_helper_t *ctx, const char *s);
+
+/**
+ * Make sure to call lexer with the proper context
+ */
+#undef yylex
+static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
+{
+	return conf_parser_lex(lvalp, ctx->scanner);
+}
+
+
+#line 129 "parser/parser.c" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "y.tab.h".  */
+#ifndef YY_CONF_PARSER_PARSER_PARSER_H_INCLUDED
+# define YY_CONF_PARSER_PARSER_PARSER_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int conf_parser_debug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    STRING = 258,
+    EQ = 259,
+    SPACES = 260,
+    NEWLINE = 261,
+    CONFIG_SETUP = 262,
+    CONN = 263,
+    CA = 264
+  };
+#endif
+/* Tokens.  */
+#define STRING 258
+#define EQ 259
+#define SPACES 260
+#define NEWLINE 261
+#define CONFIG_SETUP 262
+#define CONN 263
+#define CA 264
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE YYSTYPE;
+union YYSTYPE
+{
+#line 71 "parser/parser.y" /* yacc.c:355  */
+
+	char *s;
+	conf_parser_section_t t;
+
+#line 192 "parser/parser.c" /* yacc.c:355  */
+};
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int conf_parser_parse (parser_helper_t *ctx);
+
+#endif /* !YY_CONF_PARSER_PARSER_PARSER_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 206 "parser/parser.c" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  2
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   11
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  10
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  8
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  18
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  19
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   264
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint8 yyrline[] =
+{
+       0,    97,    97,    99,   100,   104,   105,   109,   123,   128,
+     133,   141,   144,   150,   153,   166,   178,   187,   188
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "STRING", "EQ", "SPACES", "NEWLINE",
+  "CONFIG_SETUP", "CONN", "CA", "$accept", "statements", "statement",
+  "section", "section_type", "section_name", "setting", "value", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264
+};
+# endif
+
+#define YYPACT_NINF -3
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-3)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+      -3,     0,    -3,    -2,    -3,    -3,    -3,    -3,    -3,    -3,
+      -1,     6,    -3,    -3,    -3,     1,    -3,     8,    -3
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     0,     1,    13,     3,     8,     9,    10,     4,     5,
+      11,    16,     6,    12,     7,    15,    17,    14,    18
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+      -3,    -3,    -3,    -3,    -3,    -3,    -3,    -3
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     1,     8,     9,    10,    14,    12,    17
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+       2,    11,    13,     0,    16,     3,     4,     5,     6,     7,
+      15,    18
+};
+
+static const yytype_int8 yycheck[] =
+{
+       0,     3,     3,    -1,     3,     5,     6,     7,     8,     9,
+       4,     3
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    11,     0,     5,     6,     7,     8,     9,    12,    13,
+      14,     3,    16,     3,    15,     4,     3,    17,     3
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    10,    11,    11,    11,    12,    12,    13,    14,    14,
+      14,    15,    15,    16,    16,    16,    16,    17,    17
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     2,     2,     1,     2,     2,     1,     1,
+       1,     0,     1,     0,     3,     2,     1,     1,     2
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (ctx, YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value, ctx); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_helper_t *ctx)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  YYUSE (ctx);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, parser_helper_t *ctx)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, ctx);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, parser_helper_t *ctx)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              , ctx);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule, ctx); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_helper_t *ctx)
+{
+  YYUSE (yyvaluep);
+  YYUSE (ctx);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  switch (yytype)
+    {
+          case 3: /* STRING  */
+#line 86 "parser/parser.y" /* yacc.c:1257  */
+      { free(((*yyvaluep).s)); }
+#line 1030 "parser/parser.c" /* yacc.c:1257  */
+        break;
+
+    case 15: /* section_name  */
+#line 86 "parser/parser.y" /* yacc.c:1257  */
+      { free(((*yyvaluep).s)); }
+#line 1036 "parser/parser.c" /* yacc.c:1257  */
+        break;
+
+    case 17: /* value  */
+#line 86 "parser/parser.y" /* yacc.c:1257  */
+      { free(((*yyvaluep).s)); }
+#line 1042 "parser/parser.c" /* yacc.c:1257  */
+        break;
+
+
+      default:
+        break;
+    }
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (parser_helper_t *ctx)
+{
+/* The lookahead symbol.  */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol.  */
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex (&yylval, ctx);
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 7:
+#line 110 "parser/parser.y" /* yacc.c:1646  */
+    {
+		if ((yyvsp[-1].t) != CONF_PARSER_CONFIG_SETUP && (!(yyvsp[0].s) || !strlen((yyvsp[0].s))))
+		{
+			PARSER_DBG1(ctx, "section name missing");
+			free((yyvsp[0].s));
+			YYERROR;
+		}
+		conf_parser_t *parser = (conf_parser_t*)ctx->context;
+		parser->add_section(parser, (yyvsp[-1].t), (yyvsp[0].s));
+	}
+#line 1319 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 124 "parser/parser.y" /* yacc.c:1646  */
+    {
+		(yyval.t) = CONF_PARSER_CONFIG_SETUP;
+	}
+#line 1327 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 129 "parser/parser.y" /* yacc.c:1646  */
+    {
+		(yyval.t) = CONF_PARSER_CONN;
+	}
+#line 1335 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 134 "parser/parser.y" /* yacc.c:1646  */
+    {
+		(yyval.t) = CONF_PARSER_CA;
+	}
+#line 1343 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 141 "parser/parser.y" /* yacc.c:1646  */
+    {
+		(yyval.s) = NULL;
+	}
+#line 1351 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 145 "parser/parser.y" /* yacc.c:1646  */
+    {
+		(yyval.s) = (yyvsp[0].s);
+	}
+#line 1359 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 154 "parser/parser.y" /* yacc.c:1646  */
+    {
+		if (!strlen((yyvsp[-2].s)))
+		{
+			PARSER_DBG1(ctx, "setting name can't be empty");
+			free((yyvsp[-2].s));
+			free((yyvsp[0].s));
+			YYERROR;
+		}
+		conf_parser_t *parser = (conf_parser_t*)ctx->context;
+		parser->add_setting(parser, (yyvsp[-2].s), (yyvsp[0].s));
+	}
+#line 1375 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 167 "parser/parser.y" /* yacc.c:1646  */
+    {
+		if (!strlen((yyvsp[-1].s)))
+		{
+			PARSER_DBG1(ctx, "setting name can't be empty");
+			free((yyvsp[-1].s));
+			YYERROR;
+		}
+		conf_parser_t *parser = (conf_parser_t*)ctx->context;
+		parser->add_setting(parser, (yyvsp[-1].s), NULL);
+	}
+#line 1390 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 179 "parser/parser.y" /* yacc.c:1646  */
+    {
+		PARSER_DBG1(ctx, "missing value for setting '%s'", (yyvsp[0].s));
+		free((yyvsp[0].s));
+		YYERROR;
+	}
+#line 1400 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 189 "parser/parser.y" /* yacc.c:1646  */
+    {	/* just put a single space between them, use strings for more */
+		if (asprintf(&(yyval.s), "%s %s", (yyvsp[-1].s), (yyvsp[0].s)) < 0)
+		{
+			free((yyvsp[-1].s));
+			free((yyvsp[0].s));
+			YYERROR;
+		}
+		free((yyvsp[-1].s));
+		free((yyvsp[0].s));
+	}
+#line 1415 "parser/parser.c" /* yacc.c:1646  */
+    break;
+
+
+#line 1419 "parser/parser.c" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (ctx, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (ctx, yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval, ctx);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp, ctx);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (ctx, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval, ctx);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp, ctx);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 201 "parser/parser.y" /* yacc.c:1906  */
+
+
+/**
+ * Referenced by the generated parser
+ */
+static void conf_parser_error(parser_helper_t *ctx, const char *s)
+{
+	char *text = conf_parser_get_text(ctx->scanner);
+	int len = conf_parser_get_leng(ctx->scanner);
+
+	if (len && text[len-1] == '\n')
+	{	/* cut off newline at the end to avoid muti-line log messages */
+		len--;
+	}
+	PARSER_DBG1(ctx, "%s [%.*s]", s, (int)len, text);
+}
+
+/**
+ * Parse the given file
+ */
+bool conf_parser_parse_file(conf_parser_t *this, char *name)
+{
+	parser_helper_t *helper;
+	bool success = FALSE;
+
+	helper = parser_helper_create(this);
+	helper->get_lineno = conf_parser_get_lineno;
+	if (conf_parser_lex_init_extra(helper, &helper->scanner) != 0)
+	{
+		helper->destroy(helper);
+		return FALSE;
+	}
+	helper->file_include(helper, name);
+	if (!conf_parser_open_next_file(helper))
+	{
+		DBG1(DBG_CFG, "failed to open config file '%s'", name);
+	}
+	else
+	{
+		if (getenv("DEBUG_CONF_PARSER"))
+		{
+			yydebug = 1;
+			conf_parser_set_debug(1, helper->scanner);
+		}
+		success = yyparse(helper) == 0;
+		if (!success)
+		{
+			DBG1(DBG_CFG, "invalid config file '%s'", name);
+		}
+	}
+	conf_parser_lex_destroy(helper->scanner);
+	helper->destroy(helper);
+	return success;
+}
diff --git a/src/starter/parser/parser.h b/src/starter/parser/parser.h
new file mode 100644
index 0000000..c10547b
--- /dev/null
+++ b/src/starter/parser/parser.h
@@ -0,0 +1,86 @@
+/* A Bison parser, made by GNU Bison 3.0.2.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_CONF_PARSER_PARSER_PARSER_H_INCLUDED
+# define YY_CONF_PARSER_PARSER_PARSER_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int conf_parser_debug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    STRING = 258,
+    EQ = 259,
+    SPACES = 260,
+    NEWLINE = 261,
+    CONFIG_SETUP = 262,
+    CONN = 263,
+    CA = 264
+  };
+#endif
+/* Tokens.  */
+#define STRING 258
+#define EQ 259
+#define SPACES 260
+#define NEWLINE 261
+#define CONFIG_SETUP 262
+#define CONN 263
+#define CA 264
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE YYSTYPE;
+union YYSTYPE
+{
+#line 71 "parser/parser.y" /* yacc.c:1909  */
+
+	char *s;
+	conf_parser_section_t t;
+
+#line 77 "parser/parser.h" /* yacc.c:1909  */
+};
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int conf_parser_parse (parser_helper_t *ctx);
+
+#endif /* !YY_CONF_PARSER_PARSER_PARSER_H_INCLUDED  */
diff --git a/src/starter/parser/parser.y b/src/starter/parser/parser.y
new file mode 100644
index 0000000..54dedc1
--- /dev/null
+++ b/src/starter/parser/parser.y
@@ -0,0 +1,254 @@
+%{
+/*
+ * Copyright (C) 2013-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.
+ */
+
+#define _GNU_SOURCE /* for asprintf() */
+#include <stdio.h>
+
+#include <utils/parser_helper.h>
+#include <settings/settings_types.h>
+#include <parser/conf_parser.h>
+
+#include "parser.h"
+
+#define YYDEBUG 1
+
+/**
+ * Defined by the lexer
+ */
+int conf_parser_lex(YYSTYPE *lvalp, void *scanner);
+int conf_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
+int conf_parser_lex_destroy(void *scanner);
+int conf_parser_set_in(FILE *in, void *scanner);
+void conf_parser_set_debug(int debug, void *scanner);
+char *conf_parser_get_text(void *scanner);
+int conf_parser_get_leng(void *scanner);
+int conf_parser_get_lineno(void *scanner);
+/* Custom functions in lexer */
+bool conf_parser_open_next_file(parser_helper_t *ctx);
+
+/**
+ * Forward declaration
+ */
+static void conf_parser_error(parser_helper_t *ctx, const char *s);
+
+/**
+ * Make sure to call lexer with the proper context
+ */
+#undef yylex
+static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
+{
+	return conf_parser_lex(lvalp, ctx->scanner);
+}
+
+%}
+%debug
+
+/* generate verbose error messages */
+%error-verbose
+/* generate a reentrant parser */
+%define api.pure
+/* prefix function/variable declarations */
+%name-prefix "conf_parser_"
+
+/* interact properly with the reentrant lexer */
+%lex-param {parser_helper_t *ctx}
+%parse-param {parser_helper_t *ctx}
+
+/* types for terminal symbols... */
+%union {
+	char *s;
+	conf_parser_section_t t;
+}
+%token <s> STRING
+%token EQ SPACES NEWLINE CONFIG_SETUP CONN CA
+
+/* ...and other symbols */
+%type <t> section_type
+%type <s> section_name value
+
+/* make the equal sign left associative */
+%left EQ
+
+/* properly destroy STRING tokens, which are strdup()ed, on errors */
+%destructor { free($$); } STRING section_name value
+
+/* there are two shift/reduce conflicts because we allow empty lines (and lines
+ * with spaces) within settings and anywhere else (i.e. in the beginning) */
+//%expect 2
+
+%%
+
+/**
+ * ipsec.conf grammar rules
+ */
+statements:
+	/* empty */
+	| statements NEWLINE
+	| statements statement
+	;
+
+statement:
+	section
+	| SPACES setting
+	;
+
+section:
+	section_type section_name
+	{
+		if ($1 != CONF_PARSER_CONFIG_SETUP && (!$2 || !strlen($2)))
+		{
+			PARSER_DBG1(ctx, "section name missing");
+			free($2);
+			YYERROR;
+		}
+		conf_parser_t *parser = (conf_parser_t*)ctx->context;
+		parser->add_section(parser, $1, $2);
+	}
+	;
+
+section_type:
+	CONFIG_SETUP
+	{
+		$$ = CONF_PARSER_CONFIG_SETUP;
+	}
+	|
+	CONN
+	{
+		$$ = CONF_PARSER_CONN;
+	}
+	|
+	CA
+	{
+		$$ = CONF_PARSER_CA;
+	}
+	;
+
+section_name:
+	/* empty */
+	{
+		$$ = NULL;
+	}
+	| STRING
+	{
+		$$ = $1;
+	}
+	;
+
+setting:
+	/* empty */
+	|
+	STRING EQ value
+	{
+		if (!strlen($1))
+		{
+			PARSER_DBG1(ctx, "setting name can't be empty");
+			free($1);
+			free($3);
+			YYERROR;
+		}
+		conf_parser_t *parser = (conf_parser_t*)ctx->context;
+		parser->add_setting(parser, $1, $value);
+	}
+	|
+	STRING EQ
+	{
+		if (!strlen($1))
+		{
+			PARSER_DBG1(ctx, "setting name can't be empty");
+			free($1);
+			YYERROR;
+		}
+		conf_parser_t *parser = (conf_parser_t*)ctx->context;
+		parser->add_setting(parser, $1, NULL);
+	}
+	|
+	STRING
+	{
+		PARSER_DBG1(ctx, "missing value for setting '%s'", $1);
+		free($1);
+		YYERROR;
+	}
+	;
+
+value:
+	STRING
+	| value STRING
+	{	/* just put a single space between them, use strings for more */
+		if (asprintf(&$$, "%s %s", $1, $2) < 0)
+		{
+			free($1);
+			free($2);
+			YYERROR;
+		}
+		free($1);
+		free($2);
+	}
+	;
+
+%%
+
+/**
+ * Referenced by the generated parser
+ */
+static void conf_parser_error(parser_helper_t *ctx, const char *s)
+{
+	char *text = conf_parser_get_text(ctx->scanner);
+	int len = conf_parser_get_leng(ctx->scanner);
+
+	if (len && text[len-1] == '\n')
+	{	/* cut off newline at the end to avoid muti-line log messages */
+		len--;
+	}
+	PARSER_DBG1(ctx, "%s [%.*s]", s, (int)len, text);
+}
+
+/**
+ * Parse the given file
+ */
+bool conf_parser_parse_file(conf_parser_t *this, char *name)
+{
+	parser_helper_t *helper;
+	bool success = FALSE;
+
+	helper = parser_helper_create(this);
+	helper->get_lineno = conf_parser_get_lineno;
+	if (conf_parser_lex_init_extra(helper, &helper->scanner) != 0)
+	{
+		helper->destroy(helper);
+		return FALSE;
+	}
+	helper->file_include(helper, name);
+	if (!conf_parser_open_next_file(helper))
+	{
+		DBG1(DBG_CFG, "failed to open config file '%s'", name);
+	}
+	else
+	{
+		if (getenv("DEBUG_CONF_PARSER"))
+		{
+			yydebug = 1;
+			conf_parser_set_debug(1, helper->scanner);
+		}
+		success = yyparse(helper) == 0;
+		if (!success)
+		{
+			DBG1(DBG_CFG, "invalid config file '%s'", name);
+		}
+	}
+	conf_parser_lex_destroy(helper->scanner);
+	helper->destroy(helper);
+	return success;
+}
diff --git a/src/starter/starter.c b/src/starter/starter.c
index 33916c9..ef57808 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -418,6 +418,7 @@ int main (int argc, char **argv)
 	bool no_fork = FALSE;
 	bool attach_gdb = FALSE;
 	bool load_warning = FALSE;
+	bool conftest = FALSE;
 
 	library_init(NULL, "starter");
 	atexit(library_deinit);
@@ -467,6 +468,10 @@ int main (int argc, char **argv)
 		{
 			config_file = argv[++i];
 		}
+		else if (streq(argv[i], "--conftest"))
+		{
+			conftest = TRUE;
+		}
 		else
 		{
 			usage(argv[0]);
@@ -485,6 +490,28 @@ int main (int argc, char **argv)
 
 	init_log("ipsec_starter");
 
+	if (conftest)
+	{
+		int status = LSB_RC_SUCCESS;
+
+		cfg = confread_load(config_file);
+		if (cfg == NULL || cfg->err > 0)
+		{
+			DBG1(DBG_APP, "config invalid!");
+			status = LSB_RC_INVALID_ARGUMENT;
+		}
+		else
+		{
+			DBG1(DBG_APP, "config OK");
+		}
+		if (cfg)
+		{
+			confread_free(cfg);
+		}
+		cleanup();
+		exit(status);
+	}
+
 	DBG1(DBG_APP, "Starting %sSwan "VERSION" IPsec [starter]...",
 		lib->settings->get_bool(lib->settings,
 			"charon.i_dont_care_about_security_and_use_aggressive_mode_psk",
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index fca4b1e..1e305db 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -13,16 +13,9 @@
  * for more details.
  */
 
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stddef.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 
 #include <credentials/auth_cfg.h>
 
@@ -56,48 +49,38 @@ static char* push_string(stroke_msg_t *msg, char *string)
 
 static int send_stroke_msg (stroke_msg_t *msg)
 {
-	struct sockaddr_un ctl_addr;
-	int byte_count;
-	char buffer[64];
-
-	ctl_addr.sun_family = AF_UNIX;
-	strcpy(ctl_addr.sun_path, CHARON_CTL_FILE);
+	stream_t *stream;
+	char *uri, buffer[64];
+	int count;
 
 	/* starter is not called from commandline, and therefore absolutely silent */
 	msg->output_verbosity = -1;
 
-	int sock = socket(AF_UNIX, SOCK_STREAM, 0);
-
-	if (sock < 0)
-	{
-		DBG1(DBG_APP, "socket() failed: %s", strerror(errno));
-		return -1;
-	}
-	if (connect(sock, (struct sockaddr *)&ctl_addr, offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
+	uri = lib->settings->get_str(lib->settings, "%s.plugins.stroke.socket",
+								 "unix://" CHARON_CTL_FILE, daemon_name);
+	stream = lib->streams->connect(lib->streams, uri);
+	if (!stream)
 	{
-		DBG1(DBG_APP, "connect(charon_ctl) failed: %s", strerror(errno));
-		close(sock);
+		DBG1(DBG_APP, "failed to connect to stroke socket '%s'", uri);
 		return -1;
 	}
 
-	/* send message */
-	if (write(sock, msg, msg->length) != msg->length)
+	if (!stream->write_all(stream, msg, msg->length))
 	{
-		DBG1(DBG_APP, "write(charon_ctl) failed: %s", strerror(errno));
-		close(sock);
+		DBG1(DBG_APP, "sending stroke message failed");
+		stream->destroy(stream);
 		return -1;
 	}
-	while ((byte_count = read(sock, buffer, sizeof(buffer)-1)) > 0)
+	while ((count = stream->read(stream, buffer, sizeof(buffer)-1, TRUE)) > 0)
 	{
-		buffer[byte_count] = '\0';
+		buffer[count] = '\0';
 		DBG1(DBG_APP, "%s", buffer);
 	}
-	if (byte_count < 0)
+	if (count < 0)
 	{
-		DBG1(DBG_APP, "read() failed: %s", strerror(errno));
+		DBG1(DBG_APP, "reading stroke response failed");
 	}
-
-	close(sock);
+	stream->destroy(stream);
 	return 0;
 }
 
@@ -202,6 +185,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
 	msg.add_conn.ikeme.mediated_by = push_string(&msg, conn->me_mediated_by);
 	msg.add_conn.ikeme.peerid = push_string(&msg, conn->me_peerid);
 	msg.add_conn.reqid = conn->reqid;
+	msg.add_conn.replay_window = conn->replay_window;
 	msg.add_conn.mark_in.value = conn->mark_in.value;
 	msg.add_conn.mark_in.mask = conn->mark_in.mask;
 	msg.add_conn.mark_out.value = conn->mark_out.value;
diff --git a/src/starter/tests/Makefile.am b/src/starter/tests/Makefile.am
new file mode 100644
index 0000000..f84327b
--- /dev/null
+++ b/src/starter/tests/Makefile.am
@@ -0,0 +1,19 @@
+TESTS = starter_tests
+
+check_PROGRAMS = $(TESTS)
+
+starter_tests_SOURCES = \
+	suites/test_parser.c \
+	starter_tests.h starter_tests.c
+
+starter_tests_CFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libstrongswan/tests \
+	-I$(top_srcdir)/src/starter \
+	@COVERAGE_CFLAGS@
+
+starter_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+starter_tests_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la \
+	../libstarter.la
diff --git a/src/starter/tests/Makefile.in b/src/starter/tests/Makefile.in
new file mode 100644
index 0000000..c72f23e
--- /dev/null
+++ b/src/starter/tests/Makefile.in
@@ -0,0 +1,856 @@
+# 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 = starter_tests$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1)
+subdir = src/starter/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 = starter_tests$(EXEEXT)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_starter_tests_OBJECTS = suites/starter_tests-test_parser.$(OBJEXT) \
+	starter_tests-starter_tests.$(OBJEXT)
+starter_tests_OBJECTS = $(am_starter_tests_OBJECTS)
+starter_tests_DEPENDENCIES =  \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la \
+	../libstarter.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 = 
+starter_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(starter_tests_CFLAGS) \
+	$(CFLAGS) $(starter_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 = $(starter_tests_SOURCES)
+DIST_SOURCES = $(starter_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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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@
+starter_tests_SOURCES = \
+	suites/test_parser.c \
+	starter_tests.h starter_tests.c
+
+starter_tests_CFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libstrongswan/tests \
+	-I$(top_srcdir)/src/starter \
+	@COVERAGE_CFLAGS@
+
+starter_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+starter_tests_LDADD = \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(top_builddir)/src/libstrongswan/tests/libtest.la \
+	../libstarter.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/starter/tests/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/starter/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
+suites/$(am__dirstamp):
+	@$(MKDIR_P) suites
+	@: > suites/$(am__dirstamp)
+suites/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) suites/$(DEPDIR)
+	@: > suites/$(DEPDIR)/$(am__dirstamp)
+suites/starter_tests-test_parser.$(OBJEXT): suites/$(am__dirstamp) \
+	suites/$(DEPDIR)/$(am__dirstamp)
+
+starter_tests$(EXEEXT): $(starter_tests_OBJECTS) $(starter_tests_DEPENDENCIES) $(EXTRA_starter_tests_DEPENDENCIES) 
+	@rm -f starter_tests$(EXEEXT)
+	$(AM_V_CCLD)$(starter_tests_LINK) $(starter_tests_OBJECTS) $(starter_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)/starter_tests-starter_tests.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at suites/$(DEPDIR)/starter_tests-test_parser.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 $@ $<
+
+suites/starter_tests-test_parser.o: suites/test_parser.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(starter_tests_CFLAGS) $(CFLAGS) -MT suites/starter_tests-test_parser.o -MD -MP -MF suites/$(DEPDIR)/starter_tests-test_parser.Tpo -c -o suites/starter_tests-test_parser.o `test -f 'suites/test_parser.c' || echo '$(srcdir)/'`suites/test_parser.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/starter_tests-test_parser.Tpo suites/$(DEPDIR)/starter_tests-test_parser.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_parser.c' object='suites/starter_tests-test_parser.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) $(starter_tests_CFLAGS) $(CFLAGS) -c -o suites/starter_tests-test_parser.o `test -f 'suites/test_parser.c' || echo '$(srcdir)/'`suites/test_parser.c
+
+suites/starter_tests-test_parser.obj: suites/test_parser.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(starter_tests_CFLAGS) $(CFLAGS) -MT suites/starter_tests-test_parser.obj -MD -MP -MF suites/$(DEPDIR)/starter_tests-test_parser.Tpo -c -o suites/starter_tests-test_parser.obj `if test -f 'suites/test_parser.c'; then $(CYGPATH_W) 'suites/test_parser.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_parser.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) suites/$(DEPDIR)/starter_tests-test_parser.Tpo suites/$(DEPDIR)/starter_tests-test_parser.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='suites/test_parser.c' object='suites/starter_tests-test_parser.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) $(starter_tests_CFLAGS) $(CFLAGS) -c -o suites/starter_tests-test_parser.obj `if test -f 'suites/test_parser.c'; then $(CYGPATH_W) 'suites/test_parser.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_parser.c'; fi`
+
+starter_tests-starter_tests.o: starter_tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(starter_tests_CFLAGS) $(CFLAGS) -MT starter_tests-starter_tests.o -MD -MP -MF $(DEPDIR)/starter_tests-starter_tests.Tpo -c -o starter_tests-starter_tests.o `test -f 'starter_tests.c' || echo '$(srcdir)/'`starter_tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/starter_tests-starter_tests.Tpo $(DEPDIR)/starter_tests-starter_tests.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='starter_tests.c' object='starter_tests-starter_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) $(starter_tests_CFLAGS) $(CFLAGS) -c -o starter_tests-starter_tests.o `test -f 'starter_tests.c' || echo '$(srcdir)/'`starter_tests.c
+
+starter_tests-starter_tests.obj: starter_tests.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(starter_tests_CFLAGS) $(CFLAGS) -MT starter_tests-starter_tests.obj -MD -MP -MF $(DEPDIR)/starter_tests-starter_tests.Tpo -c -o starter_tests-starter_tests.obj `if test -f 'starter_tests.c'; then $(CYGPATH_W) 'starter_tests.c'; else $(CYGPATH_W) '$(srcdir)/starter_tests.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/starter_tests-starter_tests.Tpo $(DEPDIR)/starter_tests-starter_tests.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='starter_tests.c' object='starter_tests-starter_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) $(starter_tests_CFLAGS) $(CFLAGS) -c -o starter_tests-starter_tests.obj `if test -f 'starter_tests.c'; then $(CYGPATH_W) 'starter_tests.c'; else $(CYGPATH_W) '$(srcdir)/starter_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)
+	-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 \
+	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-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:
+
+.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/starter/tests/starter_tests.c b/src/starter/tests/starter_tests.c
new file mode 100644
index 0000000..4194c52
--- /dev/null
+++ b/src/starter/tests/starter_tests.c
@@ -0,0 +1,43 @@
+/*
+ * 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>
+
+/* declare test suite constructors */
+#define TEST_SUITE(x) test_suite_t* x();
+#include "starter_tests.h"
+#undef TEST_SUITE
+
+static test_configuration_t tests[] = {
+#define TEST_SUITE(x) \
+	{ .suite = x, },
+#include "starter_tests.h"
+	{ .suite = NULL, }
+};
+
+static bool test_runner_init(bool init)
+{
+	if (!init)
+	{
+		lib->processor->set_threads(lib->processor, 0);
+		lib->processor->cancel(lib->processor);
+	}
+	return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+	return test_runner_run("stroke", tests, test_runner_init);
+}
diff --git a/src/starter/tests/starter_tests.h b/src/starter/tests/starter_tests.h
new file mode 100644
index 0000000..3486597
--- /dev/null
+++ b/src/starter/tests/starter_tests.h
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+TEST_SUITE(parser_suite_create)
diff --git a/src/starter/tests/suites/test_parser.c b/src/starter/tests/suites/test_parser.c
new file mode 100644
index 0000000..26a41ba
--- /dev/null
+++ b/src/starter/tests/suites/test_parser.c
@@ -0,0 +1,575 @@
+/*
+ * 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 <unistd.h>
+
+#include <test_suite.h>
+
+#include "../../parser/conf_parser.h"
+
+static char *path = "/tmp/strongswan-starter-parser-test";
+static conf_parser_t *parser;
+
+static void create_parser(chunk_t contents)
+{
+	ck_assert(chunk_write(contents, path, 0022, TRUE));
+	parser = conf_parser_create(path);
+}
+
+START_TEARDOWN(teardown_parser)
+{
+	parser->destroy(parser);
+	unlink(path);
+}
+END_TEARDOWN
+
+START_TEST(test_get_sections_config_setup)
+{
+	enumerator_t *enumerator;
+
+	create_parser(chunk_from_str(""));
+	ck_assert(parser->parse(parser));
+	enumerator = parser->get_sections(parser, CONF_PARSER_CONFIG_SETUP);
+	ck_assert(enumerator);
+	ck_assert(!enumerator->enumerate(enumerator, NULL));
+	enumerator->destroy(enumerator);
+	parser->destroy(parser);
+
+	create_parser(chunk_from_str("config setup\n\tfoo=bar"));
+	ck_assert(parser->parse(parser));
+	enumerator = parser->get_sections(parser, CONF_PARSER_CONFIG_SETUP);
+	ck_assert(enumerator);
+	ck_assert(!enumerator->enumerate(enumerator, NULL));
+	enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_get_sections_conn)
+{
+	enumerator_t *enumerator;
+	char *name;
+
+	create_parser(chunk_from_str(""));
+	ck_assert(parser->parse(parser));
+	enumerator = parser->get_sections(parser, CONF_PARSER_CONN);
+	ck_assert(enumerator);
+	ck_assert(!enumerator->enumerate(enumerator, NULL));
+	enumerator->destroy(enumerator);
+	parser->destroy(parser);
+
+	create_parser(chunk_from_str(
+		"conn foo\n"
+		"conn bar\n"
+		"conn foo\n"));
+	ck_assert(parser->parse(parser));
+	enumerator = parser->get_sections(parser, CONF_PARSER_CONN);
+	ck_assert(enumerator);
+	ck_assert(enumerator->enumerate(enumerator, &name));
+	ck_assert_str_eq("foo", name);
+	ck_assert(enumerator->enumerate(enumerator, &name));
+	ck_assert_str_eq("bar", name);
+	ck_assert(!enumerator->enumerate(enumerator, &name));
+	enumerator->destroy(enumerator);
+}
+END_TEST
+
+START_TEST(test_get_section_config_setup)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(""));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONFIG_SETUP, "foo");
+	ck_assert(dict);
+	dict->destroy(dict);
+	parser->destroy(parser);
+
+	create_parser(chunk_from_str("config setup\n\tfoo=bar"));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONFIG_SETUP, NULL);
+	ck_assert(dict);
+	dict->destroy(dict);
+	parser->destroy(parser);
+
+	create_parser(chunk_from_str("config setup\n\tfoo=bar"));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONFIG_SETUP, "foo");
+	ck_assert(dict);
+	dict->destroy(dict);
+}
+END_TEST
+
+START_TEST(test_get_section_conn)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(""));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "foo");
+	ck_assert(!dict);
+	parser->destroy(parser);
+
+	create_parser(chunk_from_str("conn foo\n"));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "foo");
+	ck_assert(!parser->get_section(parser, CONF_PARSER_CONN, "bar"));
+	ck_assert(dict);
+	dict->destroy(dict);
+	parser->destroy(parser);
+
+	create_parser(chunk_from_str("conn foo\n\tfoo=bar"));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "foo");
+	ck_assert(dict);
+	dict->destroy(dict);
+}
+END_TEST
+
+START_TEST(test_enumerate_values)
+{
+	enumerator_t *enumerator;
+	dictionary_t *dict;
+	char *key, *value;
+	int i;
+
+	create_parser(chunk_from_str(
+		"conn foo\n"
+		"	foo=bar\n"
+		"	bar=baz"));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "foo");
+	ck_assert(dict);
+	ck_assert_str_eq("bar", dict->get(dict, "foo"));
+	ck_assert_str_eq("baz", dict->get(dict, "bar"));
+	enumerator = dict->create_enumerator(dict);
+	for (i = 0; enumerator->enumerate(enumerator, &key, &value); i++)
+	{
+		if ((streq(key, "foo") && !streq(value, "bar")) ||
+			(streq(key, "bar") && !streq(value, "baz")))
+		{
+			fail("unexpected setting %s=%s", key, value);
+		}
+	}
+	enumerator->destroy(enumerator);
+	ck_assert_int_eq(i, 2);
+	dict->destroy(dict);
+}
+END_TEST
+
+#define extensibility_config(section) \
+	section "\n" \
+	"	foo=bar\n" \
+	"	dup=one\n" \
+	"	dup=two\n" \
+	"\n" \
+	"	nope=val\n" \
+	"\n" \
+	section "\n" \
+	"	foo=baz\n" \
+	section "\n" \
+	"	answer=42\n" \
+	"	nope=\n"
+
+static struct {
+	char *conf;
+	conf_parser_section_t type;
+	char *name;
+} extensibility_data[] = {
+	{ extensibility_config("config setup"), CONF_PARSER_CONFIG_SETUP, NULL },
+	{ extensibility_config("ca ca-foo"), CONF_PARSER_CA, "ca-foo" },
+	{ extensibility_config("conn conn-foo"), CONF_PARSER_CONN, "conn-foo" },
+};
+
+START_TEST(test_extensibility)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(extensibility_data[_i].conf));
+	ck_assert(parser->parse(parser));
+
+	dict = parser->get_section(parser, extensibility_data[_i].type,
+							   extensibility_data[_i].name);
+	ck_assert(dict);
+	ck_assert_str_eq("baz", dict->get(dict, "foo"));
+	ck_assert_str_eq("two", dict->get(dict, "dup"));
+	ck_assert_str_eq("42", dict->get(dict, "answer"));
+	ck_assert(!dict->get(dict, "nope"));
+	ck_assert(!dict->get(dict, "anything"));
+	dict->destroy(dict);
+}
+END_TEST
+
+static struct {
+	char *conf;
+	bool check_section;
+	char *value;
+} comments_data[] = {
+	{ "# conn foo", FALSE, NULL },
+	{ "# conn foo\n", FALSE, NULL },
+	{ "conn foo # asdf", TRUE, NULL },
+	{ "conn foo # asdf", TRUE, NULL },
+	{ "conn foo# asdf\n", TRUE, NULL },
+	{ "conn foo # asdf\n\tkey=val", TRUE, "val" },
+	{ "conn foo # asdf\n#\tkey=val", TRUE, NULL },
+	{ "conn foo # asdf\n\t#key=val", TRUE, NULL },
+	{ "conn foo # asdf\n\tkey=@#keyid", TRUE, "@#keyid" },
+	{ "conn foo # asdf\n\tkey=\"@#keyid\"", TRUE, "@#keyid" },
+	{ "conn foo # asdf\n\tkey=asdf@#keyid", TRUE, "asdf@" },
+	{ "conn foo # asdf\n\tkey=#val", TRUE, NULL },
+	{ "conn foo # asdf\n\tkey=val#asdf", TRUE, "val" },
+	{ "conn foo # asdf\n\tkey=\"val#asdf\"", TRUE, "val#asdf" },
+	{ "conn foo # asdf\n\tkey=val # asdf\n", TRUE, "val" },
+	{ "conn foo # asdf\n# asdf\n\tkey=val\n", TRUE, "val" },
+	{ "conn foo # asdf\n\t# asdf\n\tkey=val\n", TRUE, "val" },
+};
+
+START_TEST(test_comments)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(comments_data[_i].conf));
+	ck_assert(parser->parse(parser));
+	if (comments_data[_i].check_section)
+	{
+		dict = parser->get_section(parser, CONF_PARSER_CONN, "foo");
+		ck_assert(dict);
+		if (comments_data[_i].value)
+		{
+			ck_assert_str_eq(comments_data[_i].value, dict->get(dict, "key"));
+		}
+		else
+		{
+			ck_assert(!dict->get(dict, "key"));
+		}
+		dict->destroy(dict);
+	}
+	else
+	{
+		ck_assert(!parser->get_section(parser, CONF_PARSER_CONN, "foo"));
+	}
+}
+END_TEST
+
+static struct {
+	char *conf;
+	bool check_section;
+	char *value;
+} whitespace_data[] = {
+	{ "conn foo   ", FALSE, NULL },
+	{ "conn    foo", FALSE, NULL },
+	{ "conn    foo\n", FALSE, NULL },
+	{ "conn    foo  \n", FALSE, NULL },
+	{ "conn foo\n   ", FALSE, NULL },
+	{ "conn foo\n   \n", FALSE, NULL },
+	{ "conn foo\nconn bar", TRUE, NULL },
+	{ "conn foo\n   \nconn bar", TRUE, NULL },
+	{ "conn foo\n key=val", FALSE, "val" },
+	{ "conn foo\n\tkey=val", FALSE, "val" },
+	{ "conn foo\n\t  \tkey=val", FALSE, "val" },
+	{ "conn foo\n\tkey  =  val  ", FALSE, "val" },
+};
+
+START_TEST(test_whitespace)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(whitespace_data[_i].conf));
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "foo");
+	ck_assert(dict);
+	if (whitespace_data[_i].value)
+	{
+		ck_assert_str_eq(whitespace_data[_i].value, dict->get(dict, "key"));
+	}
+	else
+	{
+		ck_assert(!dict->get(dict, "key"));
+	}
+	dict->destroy(dict);
+	if (whitespace_data[_i].check_section)
+	{
+		dict = parser->get_section(parser, CONF_PARSER_CONN, "bar");
+		ck_assert(dict);
+		dict->destroy(dict);
+	}
+	else
+	{
+		ck_assert(!parser->get_section(parser, CONF_PARSER_CONN, "bar"));
+	}
+}
+END_TEST
+
+static struct {
+	bool valid;
+	char *conf;
+	char *section;
+	char *value;
+} strings_data[] = {
+	{ FALSE, "\"conn foo\"", NULL, NULL },
+	{ TRUE, "conn \"foo\"", "foo", NULL },
+	{ FALSE, "conn foo bar", NULL, NULL },
+	{ TRUE, "conn \"foo bar\"", "foo bar", NULL },
+	{ TRUE, "conn \"#foo\"", "#foo", NULL },
+	{ FALSE, "conn foo\n\t\"key=val\"", "foo", NULL },
+	{ TRUE, "conn foo\n\t\"key\"=val", "foo", "val" },
+	{ TRUE, "conn foo\n\tkey=val ue", "foo", "val ue" },
+	{ TRUE, "conn foo\n\tkey=val     ue", "foo", "val ue" },
+	{ TRUE, "conn foo\n\tkey=\"val   ue\"", "foo", "val   ue" },
+	{ TRUE, "conn foo\n\tkey=\"val\\nue\"", "foo", "val\nue" },
+};
+
+START_TEST(test_strings)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(strings_data[_i].conf));
+	ck_assert(parser->parse(parser) == strings_data[_i].valid);
+	if (strings_data[_i].section)
+	{
+		dict = parser->get_section(parser, CONF_PARSER_CONN,
+								   strings_data[_i].section);
+		ck_assert(dict);
+		if (strings_data[_i].value)
+		{
+			ck_assert_str_eq(strings_data[_i].value, dict->get(dict, "key"));
+		}
+		else
+		{
+			ck_assert(!dict->get(dict, "key"));
+		}
+		dict->destroy(dict);
+	}
+}
+END_TEST
+
+START_TEST(test_refcounting)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(
+		"conn foo\n"
+		"	key=val"));
+
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "foo");
+	ck_assert(dict);
+	ck_assert_str_eq("val", dict->get(dict, "key"));
+	parser->destroy(parser);
+	ck_assert_str_eq("val", dict->get(dict, "key"));
+	dict->destroy(dict);
+}
+END_TEST
+
+START_TEST(test_default)
+{
+	enumerator_t *enumerator;
+	dictionary_t *dict;
+	char *name;
+
+	create_parser(chunk_from_str(
+		"conn %default\n"
+		"	key=valdef\n"
+		"	unset=set\n"
+		"conn A\n"
+		"	key=vala\n"
+		"	unset=\n"
+		"conn B\n"
+		"	keyb=valb\n"
+		""));
+
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "%default");
+	ck_assert(!dict);
+	enumerator = parser->get_sections(parser, CONF_PARSER_CONN);
+	ck_assert(enumerator);
+	ck_assert(enumerator->enumerate(enumerator, &name));
+	ck_assert_str_eq("A", name);
+	ck_assert(enumerator->enumerate(enumerator, &name));
+	ck_assert_str_eq("B", name);
+	ck_assert(!enumerator->enumerate(enumerator, &name));
+	enumerator->destroy(enumerator);
+
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "A");
+	ck_assert(dict);
+	ck_assert_str_eq("vala", dict->get(dict, "key"));
+	ck_assert(!dict->get(dict, "unset"));
+	dict->destroy(dict);
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "B");
+	ck_assert(dict);
+	ck_assert_str_eq("valdef", dict->get(dict, "key"));
+	ck_assert_str_eq("valb", dict->get(dict, "keyb"));
+	ck_assert_str_eq("set", dict->get(dict, "unset"));
+	dict->destroy(dict);
+}
+END_TEST
+
+START_TEST(test_also)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(
+		"conn A\n"
+		"	key=vala\n"
+		"	keya=val1\n"
+		"	unset=set\n"
+		"conn B\n"
+		"	also=A\n"
+		"	key=valb\n"
+		"	keyb=val2\n"
+		"	unset=\n"
+		"conn C\n"
+		"	keyc=val3\n"
+		"	unset=set again\n"
+		"	also=B\n"
+		"conn D\n"
+		"	keyd=val4\n"
+		"	also=A\n"
+		"	also=B\n"
+		"conn E\n"
+		"	keye=val5\n"
+		"	also=B\n"
+		"	also=A\n"
+		""));
+
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "B");
+	ck_assert(dict);
+	ck_assert_str_eq("valb", dict->get(dict, "key"));
+	ck_assert_str_eq("val1", dict->get(dict, "keya"));
+	ck_assert_str_eq("val2", dict->get(dict, "keyb"));
+	ck_assert(!dict->get(dict, "unset"));
+	dict->destroy(dict);
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "C");
+	ck_assert(dict);
+	ck_assert_str_eq("valb", dict->get(dict, "key"));
+	ck_assert_str_eq("val1", dict->get(dict, "keya"));
+	ck_assert_str_eq("val2", dict->get(dict, "keyb"));
+	ck_assert_str_eq("val3", dict->get(dict, "keyc"));
+	ck_assert_str_eq("set again", dict->get(dict, "unset"));
+	dict->destroy(dict);
+	/* since B includes A too the inclusion in D and E has no effect */
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "D");
+	ck_assert(dict);
+	ck_assert_str_eq("valb", dict->get(dict, "key"));
+	ck_assert_str_eq("val1", dict->get(dict, "keya"));
+	ck_assert_str_eq("val2", dict->get(dict, "keyb"));
+	ck_assert(!dict->get(dict, "keyc"));
+	ck_assert_str_eq("val4", dict->get(dict, "keyd"));
+	ck_assert(!dict->get(dict, "unset"));
+	dict->destroy(dict);
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "E");
+	ck_assert(dict);
+	ck_assert_str_eq("valb", dict->get(dict, "key"));
+	ck_assert_str_eq("val1", dict->get(dict, "keya"));
+	ck_assert_str_eq("val2", dict->get(dict, "keyb"));
+	ck_assert(!dict->get(dict, "keyc"));
+	ck_assert(!dict->get(dict, "keyd"));
+	ck_assert_str_eq("val5", dict->get(dict, "keye"));
+	ck_assert(!dict->get(dict, "unset"));
+	dict->destroy(dict);
+}
+END_TEST
+
+START_TEST(test_ambiguous)
+{
+	dictionary_t *dict;
+
+	create_parser(chunk_from_str(
+		"conn A\n"
+		"	key=vala\n"
+		"conn B\n"
+		"	key=valb\n"
+		"conn C\n"
+		"	also=A\n"
+		"	also=B\n"
+		"conn D\n"
+		"	also=B\n"
+		"	also=A\n"
+		"conn E\n"
+		"	also=C\n"
+		"	also=D\n"
+		"conn F\n"
+		"	also=D\n"
+		"	also=C\n"));
+
+	ck_assert(parser->parse(parser));
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "E");
+	ck_assert(dict);
+	ck_assert_str_eq("valb", dict->get(dict, "key"));
+	dict->destroy(dict);
+	dict = parser->get_section(parser, CONF_PARSER_CONN, "F");
+	ck_assert(dict);
+	ck_assert_str_eq("vala", dict->get(dict, "key"));
+	dict->destroy(dict);
+}
+END_TEST
+
+Suite *parser_suite_create()
+{
+	Suite *s;
+	TCase *tc;
+
+	s = suite_create("ipsec.conf parser");
+
+	tc = tcase_create("get_section(s)");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_test(tc, test_get_sections_config_setup);
+	tcase_add_test(tc, test_get_sections_conn);
+	tcase_add_test(tc, test_get_section_config_setup);
+	tcase_add_test(tc, test_get_section_conn);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("enumerate settings");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_test(tc, test_enumerate_values);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("extensibility");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_loop_test(tc, test_extensibility, 0, countof(extensibility_data));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("comments");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_loop_test(tc, test_comments, 0, countof(comments_data));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("whitespace");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_loop_test(tc, test_whitespace, 0, countof(whitespace_data));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("strings");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_loop_test(tc, test_strings, 0, countof(strings_data));
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("refcounting");
+	tcase_add_test(tc, test_refcounting);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("%default");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_test(tc, test_default);
+	suite_add_tcase(s, tc);
+
+	tc = tcase_create("also=");
+	tcase_add_checked_fixture(tc, NULL, teardown_parser);
+	tcase_add_test(tc, test_also);
+	tcase_add_test(tc, test_ambiguous);
+	suite_add_tcase(s, tc);
+
+	return s;
+}
diff --git a/src/stroke/Makefile.in b/src/stroke/Makefile.in
index 61136e8..1741b64 100644
--- a/src/stroke/Makefile.in
+++ b/src/stroke/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -234,6 +234,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -252,6 +253,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -279,6 +281,7 @@ 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@
@@ -370,6 +373,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index 69c8ea2..ae20b0c 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -1,5 +1,5 @@
-/* Stroke for charon is the counterpart to whack from pluto
- * Copyright (C) 2007-2012 Tobias Brunner
+/*
+ * Copyright (C) 2007-2014 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -15,16 +15,10 @@
  */
 
 #include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
 #include <unistd.h>
-#include <dirent.h>
-#include <errno.h>
 #include <stdio.h>
-#include <stddef.h>
 #include <string.h>
+#include <getopt.h>
 
 #include <library.h>
 
@@ -36,6 +30,7 @@ struct stroke_token {
     stroke_keyword_t kw;
 };
 
+static char *daemon_name = "charon";
 static int output_verbosity = 1; /* CONTROL */
 
 static char* push_string(stroke_msg_t *msg, char *string)
@@ -56,48 +51,36 @@ static char* push_string(stroke_msg_t *msg, char *string)
 
 static int send_stroke_msg (stroke_msg_t *msg)
 {
-	struct sockaddr_un ctl_addr;
-	int sock, byte_count;
-	char buffer[512], *pass;
-
-	ctl_addr.sun_family = AF_UNIX;
-	strcpy(ctl_addr.sun_path, STROKE_SOCKET);
+	stream_t *stream;
+	char *uri, buffer[512], *pass;
+	int count;
 
 	msg->output_verbosity = output_verbosity;
 
-	sock = socket(AF_UNIX, SOCK_STREAM, 0);
-	if (sock < 0)
-	{
-		fprintf(stderr, "Opening unix socket %s: %s\n", STROKE_SOCKET, strerror(errno));
-		return -1;
-	}
-	if (connect(sock, (struct sockaddr *)&ctl_addr,
-				offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
+	uri = lib->settings->get_str(lib->settings, "%s.plugins.stroke.socket",
+								 "unix://" STROKE_SOCKET, daemon_name);
+	stream = lib->streams->connect(lib->streams, uri);
+	if (!stream)
 	{
-		fprintf(stderr, "Connect to socket failed: %s\n", strerror(errno));
-		close(sock);
+		fprintf(stderr, "failed to connect to stroke socket '%s'\n", uri);
 		return -1;
 	}
 
-	/* send message */
-	if (write(sock, msg, msg->length) != msg->length)
+	if (!stream->write_all(stream, msg, msg->length))
 	{
-		fprintf(stderr, "writing to socket failed: %s\n", strerror(errno));
-		close(sock);
+		fprintf(stderr, "sending stroke message failed\n");
+		stream->destroy(stream);
 		return -1;
 	}
 
-	while ((byte_count = read(sock, buffer, sizeof(buffer)-1)) > 0)
+	while ((count = stream->read(stream, buffer, sizeof(buffer)-1, TRUE)) > 0)
 	{
-		buffer[byte_count] = '\0';
+		buffer[count] = '\0';
 
 		/* we prompt if we receive a magic keyword */
-		if ((byte_count >= 12 &&
-			 streq(buffer + byte_count - 12, "Passphrase:\n")) ||
-			(byte_count >= 10 &&
-			 streq(buffer + byte_count - 10, "Password:\n")) ||
-			(byte_count >= 5 &&
-			 streq(buffer + byte_count - 5, "PIN:\n")))
+		if ((count >= 12 && streq(buffer + count - 12, "Passphrase:\n")) ||
+			(count >= 10 && streq(buffer + count - 10, "Password:\n")) ||
+			(count >=  5 && streq(buffer + count -  5, "PIN:\n")))
 		{
 			/* remove trailing newline */
 			pass = strrchr(buffer, '\n');
@@ -112,8 +95,8 @@ static int send_stroke_msg (stroke_msg_t *msg)
 #endif
 			if (pass)
 			{
-				ignore_result(write(sock, pass, strlen(pass)));
-				ignore_result(write(sock, "\n", 1));
+				stream->write_all(stream, pass, strlen(pass));
+				stream->write_all(stream, "\n", 1);
 			}
 		}
 		else
@@ -121,12 +104,11 @@ static int send_stroke_msg (stroke_msg_t *msg)
 			printf("%s", buffer);
 		}
 	}
-	if (byte_count < 0)
+	if (count < 0)
 	{
-		fprintf(stderr, "reading from socket failed: %s\n", strerror(errno));
+		fprintf(stderr, "reading stroke response failed\n");
 	}
-
-	close(sock);
+	stream->destroy(stream);
 	return 0;
 }
 
@@ -393,187 +375,215 @@ static int set_loglevel(char *type, u_int level)
 	return send_stroke_msg(&msg);
 }
 
-static void exit_error(char *error)
+static int usage(char *error)
 {
+	FILE *out = error ? stderr : stdout;
+
+	fprintf(out, "stroke [OPTIONS] command [ARGUMENTS]\n\n");
+	fprintf(out, "Options:\n");
+	fprintf(out, "  -h, --help             print this information.\n");
+	fprintf(out, "  -d, --daemon=NAME      name of the daemon.\n");
+	fprintf(out, "Commands:\n");
+	fprintf(out, "  Add a connection:\n");
+	fprintf(out, "    stroke add NAME MY_ID OTHER_ID MY_ADDR OTHER_ADDR\\\n");
+	fprintf(out, "           MY_NET OTHER_NET\n");
+	fprintf(out, "    where: ID is any IKEv2 ID \n");
+	fprintf(out, "           ADDR is a IPv4 address\n");
+	fprintf(out, "           NET is a IPv4 subnet in CIDR notation\n");
+	fprintf(out, "  Delete a connection:\n");
+	fprintf(out, "    stroke delete NAME\n");
+	fprintf(out, "    where: NAME is a connection name added with \"stroke add\"\n");
+	fprintf(out, "  Initiate a connection:\n");
+	fprintf(out, "    stroke up NAME\n");
+	fprintf(out, "    where: NAME is a connection name added with \"stroke add\"\n");
+	fprintf(out, "  Initiate a connection without blocking:\n");
+	fprintf(out, "    stroke up-nb NAME\n");
+	fprintf(out, "    where: NAME is a connection name added with \"stroke add\"\n");
+	fprintf(out, "  Terminate a connection:\n");
+	fprintf(out, "    stroke down NAME\n");
+	fprintf(out, "    where: NAME is a connection name added with \"stroke add\"\n");
+	fprintf(out, "  Terminate a connection without blocking:\n");
+	fprintf(out, "    stroke down-nb NAME\n");
+	fprintf(out, "    where: NAME is a connection name added with \"stroke add\"\n");
+	fprintf(out, "  Terminate a connection by remote srcip:\n");
+	fprintf(out, "    stroke down-srcip START [END]\n");
+	fprintf(out, "    where: START and optional END define the clients source IP\n");
+	fprintf(out, "  Set loglevel for a logging type:\n");
+	fprintf(out, "    stroke loglevel TYPE LEVEL\n");
+	fprintf(out, "    where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib\n");
+	fprintf(out, "           LEVEL is -1|0|1|2|3|4\n");
+	fprintf(out, "  Show connection status:\n");
+	fprintf(out, "    stroke status\n");
+	fprintf(out, "  Show extended status information:\n");
+	fprintf(out, "    stroke statusall\n");
+	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, "  Show list of end entity certificates, ca info records  and crls:\n");
+	fprintf(out, "    stroke listcerts|listcainfos|listcrls|listall\n");
+	fprintf(out, "  Show list of supported algorithms:\n");
+	fprintf(out, "    stroke listalgs\n");
+	fprintf(out, "  Reload authority and attribute certificates:\n");
+	fprintf(out, "    stroke rereadcacerts|rereadocspcerts|rereadaacerts|rereadacerts\n");
+	fprintf(out, "  Reload secrets and crls:\n");
+	fprintf(out, "    stroke rereadsecrets|rereadcrls|rereadall\n");
+	fprintf(out, "  Purge ocsp cache entries:\n");
+	fprintf(out, "    stroke purgeocsp\n");
+	fprintf(out, "  Purge CRL cache entries:\n");
+	fprintf(out, "    stroke purgecrls\n");
+	fprintf(out, "  Purge X509 cache entries:\n");
+	fprintf(out, "    stroke purgecerts\n");
+	fprintf(out, "  Purge IKE_SAs without a CHILD_SA:\n");
+	fprintf(out, "    stroke purgeike\n");
+	fprintf(out, "  Export credentials to the console:\n");
+	fprintf(out, "    stroke exportx509 DN\n");
+	fprintf(out, "    stroke exportconncert connname\n");
+	fprintf(out, "    stroke exportconnchain connname\n");
+	fprintf(out, "  Show current memory usage:\n");
+	fprintf(out, "    stroke memusage\n");
+	fprintf(out, "  Show leases of a pool:\n");
+	fprintf(out, "    stroke leases [POOL [ADDRESS]]\n");
+	fprintf(out, "  Set username and password for a connection:\n");
+	fprintf(out, "    stroke user-creds NAME USERNAME [PASSWORD]\n");
+	fprintf(out, "    where: NAME is a connection name added with \"stroke add\"\n");
+	fprintf(out, "           USERNAME is the username\n");
+	fprintf(out, "           PASSWORD is the optional password, you'll be asked to enter it if not given\n");
+	fprintf(out, "  Show IKE counters:\n");
+	fprintf(out, "    stroke listcounters [connection-name]\n");
+
 	if (error)
 	{
-		fprintf(stderr, "%s\n", error);
+		fprintf(out, "\nError: %s\n", error);
+		return -1;
 	}
-	exit(-1);
-}
-
-static void exit_usage(char *error)
-{
-	printf("Usage:\n");
-	printf("  Add a connection:\n");
-	printf("    stroke add NAME MY_ID OTHER_ID MY_ADDR OTHER_ADDR\\\n");
-	printf("           MY_NET OTHER_NET\n");
-	printf("    where: ID is any IKEv2 ID \n");
-	printf("           ADDR is a IPv4 address\n");
-	printf("           NET is a IPv4 subnet in CIDR notation\n");
-	printf("  Delete a connection:\n");
-	printf("    stroke delete NAME\n");
-	printf("    where: NAME is a connection name added with \"stroke add\"\n");
-	printf("  Initiate a connection:\n");
-	printf("    stroke up NAME\n");
-	printf("    where: NAME is a connection name added with \"stroke add\"\n");
-	printf("  Initiate a connection without blocking:\n");
-	printf("    stroke up-nb NAME\n");
-	printf("    where: NAME is a connection name added with \"stroke add\"\n");
-	printf("  Terminate a connection:\n");
-	printf("    stroke down NAME\n");
-	printf("    where: NAME is a connection name added with \"stroke add\"\n");
-	printf("  Terminate a connection without blocking:\n");
-	printf("    stroke down-nb NAME\n");
-	printf("    where: NAME is a connection name added with \"stroke add\"\n");
-	printf("  Terminate a connection by remote srcip:\n");
-	printf("    stroke down-srcip START [END]\n");
-	printf("    where: START and optional END define the clients source IP\n");
-	printf("  Set loglevel for a logging type:\n");
-	printf("    stroke loglevel TYPE LEVEL\n");
-	printf("    where: TYPE is any|dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib\n");
-	printf("           LEVEL is -1|0|1|2|3|4\n");
-	printf("  Show connection status:\n");
-	printf("    stroke status\n");
-	printf("  Show extended status information:\n");
-	printf("    stroke statusall\n");
-	printf("  Show extended status information without blocking:\n");
-	printf("    stroke statusall-nb\n");
-	printf("  Show list of authority and attribute certificates:\n");
-	printf("    stroke listcacerts|listocspcerts|listaacerts|listacerts\n");
-	printf("  Show list of end entity certificates, ca info records  and crls:\n");
-	printf("    stroke listcerts|listcainfos|listcrls|listall\n");
-	printf("  Show list of supported algorithms:\n");
-	printf("    stroke listalgs\n");
-	printf("  Reload authority and attribute certificates:\n");
-	printf("    stroke rereadcacerts|rereadocspcerts|rereadaacerts|rereadacerts\n");
-	printf("  Reload secrets and crls:\n");
-	printf("    stroke rereadsecrets|rereadcrls|rereadall\n");
-	printf("  Purge ocsp cache entries:\n");
-	printf("    stroke purgeocsp\n");
-	printf("  Purge CRL cache entries:\n");
-	printf("    stroke purgecrls\n");
-	printf("  Purge X509 cache entries:\n");
-	printf("    stroke purgecerts\n");
-	printf("  Purge IKE_SAs without a CHILD_SA:\n");
-	printf("    stroke purgeike\n");
-	printf("  Export credentials to the console:\n");
-	printf("    stroke exportx509 DN\n");
-	printf("    stroke exportconncert connname\n");
-	printf("    stroke exportconnchain connname\n");
-	printf("  Show current memory usage:\n");
-	printf("    stroke memusage\n");
-	printf("  Show leases of a pool:\n");
-	printf("    stroke leases [POOL [ADDRESS]]\n");
-	printf("  Set username and password for a connection:\n");
-	printf("    stroke user-creds NAME USERNAME [PASSWORD]\n");
-	printf("    where: NAME is a connection name added with \"stroke add\"\n");
-	printf("           USERNAME is the username\n");
-	printf("           PASSWORD is the optional password, you'll be asked to enter it if not given\n");
-	printf("  Show IKE counters:\n");
-	printf("    stroke listcounters [connection-name]\n");
-	exit_error(error);
+	return 0;
 }
 
 int main(int argc, char *argv[])
 {
 	const stroke_token_t *token;
+	char *cmd;
 	int res = 0;
 
 	library_init(NULL, "stroke");
 	atexit(library_deinit);
 
-	if (argc < 2)
+	while (true)
 	{
-		exit_usage(NULL);
+		struct option long_opts[] = {
+			{"help",		no_argument,		NULL,	'h' },
+			{"daemon",		required_argument,	NULL,	'd' },
+			{0,0,0,0},
+		};
+		switch (getopt_long(argc, argv, "hd:", long_opts, NULL))
+		{
+			case EOF:
+				break;
+			case 'h':
+				return usage(NULL);
+			case 'd':
+				daemon_name = optarg;
+				continue;
+			default:
+				return usage("invalid option");
+		}
+		break;
 	}
 
-	token = in_word_set(argv[1], strlen(argv[1]));
+	if (optind == argc)
+	{
+		return usage("command missing");
+	}
 
+	cmd = argv[optind++];
+	token = in_word_set(cmd, strlen(cmd));
 	if (token == NULL)
 	{
-		exit_usage("unknown keyword");
+		return usage("unknown command");
 	}
 
+	/* make argv/argc only cover positional arguments */
+	argv = &argv[optind];
+	argc = argc - optind;
+
 	switch (token->kw)
 	{
 		case STROKE_ADD:
-			if (argc < 9)
+			if (argc < 7)
 			{
-				exit_usage("\"add\" needs more parameters...");
+				return usage("\"add\" needs more arguments...");
 			}
-			res = add_connection(argv[2],
-								 argv[3], argv[4],
-								 argv[5], argv[6],
-								 argv[7], argv[8]);
+			res = add_connection(argv[0], argv[1], argv[2], argv[3], argv[4],
+								 argv[5], argv[6]);
 			break;
 		case STROKE_DELETE:
 		case STROKE_DEL:
-			if (argc < 3)
+			if (argc < 1)
 			{
-				exit_usage("\"delete\" needs a connection name");
+				return usage("\"delete\" needs a connection name");
 			}
-			res = del_connection(argv[2]);
+			res = del_connection(argv[0]);
 			break;
 		case STROKE_UP_NOBLK:
 			output_verbosity = -1;
 			/* fall-through */
 		case STROKE_UP:
-			if (argc < 3)
+			if (argc < 1)
 			{
-				exit_usage("\"up\" needs a connection name");
+				return usage("\"up\" needs a connection name");
 			}
-			res = initiate_connection(argv[2]);
+			res = initiate_connection(argv[0]);
 			break;
 		case STROKE_DOWN_NOBLK:
 			output_verbosity = -1;
 			/* fall-through */
 		case STROKE_DOWN:
-			if (argc < 3)
+			if (argc < 1)
 			{
-				exit_usage("\"down\" needs a connection name");
+				return usage("\"down\" needs a connection name");
 			}
-			res = terminate_connection(argv[2]);
+			res = terminate_connection(argv[0]);
 			break;
 		case STROKE_DOWN_SRCIP:
-			if (argc < 3)
+			if (argc < 1)
 			{
-				exit_usage("\"down-srcip\" needs start and optional end address");
+				return usage("\"down-srcip\" needs start and optional end address");
 			}
-			res = terminate_connection_srcip(argv[2], argc > 3 ? argv[3] : NULL);
+			res = terminate_connection_srcip(argv[0], argc > 1 ? argv[1] : NULL);
 			break;
 		case STROKE_REKEY:
-			if (argc < 3)
+			if (argc < 1)
 			{
-				exit_usage("\"rekey\" needs a connection name");
+				return usage("\"rekey\" needs a connection name");
 			}
-			res = rekey_connection(argv[2]);
+			res = rekey_connection(argv[0]);
 			break;
 		case STROKE_ROUTE:
-			if (argc < 3)
+			if (argc < 1)
 			{
-				exit_usage("\"route\" needs a connection name");
+				return usage("\"route\" needs a connection name");
 			}
-			res = route_connection(argv[2]);
+			res = route_connection(argv[0]);
 			break;
 		case STROKE_UNROUTE:
-			if (argc < 3)
+			if (argc < 1)
 			{
-				exit_usage("\"unroute\" needs a connection name");
+				return usage("\"unroute\" needs a connection name");
 			}
-			res = unroute_connection(argv[2]);
+			res = unroute_connection(argv[0]);
 			break;
 		case STROKE_LOGLEVEL:
-			if (argc < 4)
+			if (argc < 2)
 			{
-				exit_usage("\"logtype\" needs more parameters...");
+				return usage("\"logtype\" needs more parameters...");
 			}
-			res = set_loglevel(argv[2], atoi(argv[3]));
+			res = set_loglevel(argv[0], atoi(argv[1]));
 			break;
 		case STROKE_STATUS:
 		case STROKE_STATUSALL:
 		case STROKE_STATUSALL_NOBLK:
-			res = show_status(token->kw, argc > 2 ? argv[2] : NULL);
+			res = show_status(token->kw, argc ? argv[0] : NULL);
 			break;
 		case STROKE_LIST_PUBKEYS:
 		case STROKE_LIST_CERTS:
@@ -587,7 +597,7 @@ int main(int argc, char *argv[])
 		case STROKE_LIST_ALGS:
 		case STROKE_LIST_PLUGINS:
 		case STROKE_LIST_ALL:
-			res = list(token->kw, argc > 2 && streq(argv[2], "--utc"));
+			res = list(token->kw, argc && streq(argv[0], "--utc"));
 			break;
 		case STROKE_REREAD_SECRETS:
 		case STROKE_REREAD_CACERTS:
@@ -607,34 +617,34 @@ int main(int argc, char *argv[])
 		case STROKE_EXPORT_X509:
 		case STROKE_EXPORT_CONN_CERT:
 		case STROKE_EXPORT_CONN_CHAIN:
-			if (argc != 3)
+			if (argc < 1)
 			{
-				exit_usage("\"export\" needs a name");
+				return usage("\"export\" needs a name");
 			}
-			res = export(token->kw, argv[2]);
+			res = export(token->kw, argv[0]);
 			break;
 		case STROKE_LEASES:
-			res = leases(token->kw, argc > 2 ? argv[2] : NULL,
-						 argc > 3 ? argv[3] : NULL);
+			res = leases(token->kw, argc ? argv[0] : NULL,
+						 argc > 1 ? argv[1] : NULL);
 			break;
 		case STROKE_MEMUSAGE:
 			res = memusage();
 			break;
 		case STROKE_USER_CREDS:
-			if (argc < 4)
+			if (argc < 2)
 			{
-				exit_usage("\"user-creds\" needs a connection name, "
+				return usage("\"user-creds\" needs a connection name, "
 						   "username and optionally a password");
 			}
-			res = user_credentials(argv[2], argv[3], argc > 4 ? argv[4] : NULL);
+			res = user_credentials(argv[0], argv[1], argc > 2 ? argv[2] : NULL);
 			break;
 		case STROKE_COUNTERS:
 		case STROKE_COUNTERS_RESET:
 			res = counters(token->kw == STROKE_COUNTERS_RESET,
-						   argc > 2 ? argv[2] : NULL);
+						   argc ? argv[0] : NULL);
 			break;
 		default:
-			exit_usage(NULL);
+			return usage(NULL);
 	}
 	return res;
 }
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index 5ece724..60886cf 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -304,6 +304,7 @@ struct stroke_msg_t {
 				u_int32_t mask;
 			} mark_in, mark_out;
 			stroke_end_t me, other;
+			u_int32_t replay_window;
 		} add_conn;
 
 		/* data for STR_ADD_CA */
diff --git a/src/swanctl/Makefile.am b/src/swanctl/Makefile.am
new file mode 100644
index 0000000..385737a
--- /dev/null
+++ b/src/swanctl/Makefile.am
@@ -0,0 +1,66 @@
+sbin_PROGRAMS = swanctl
+
+swanctl_SOURCES = \
+	command.c command.h \
+	commands/initiate.c \
+	commands/terminate.c \
+	commands/install.c \
+	commands/list_sas.c \
+	commands/list_pols.c \
+	commands/list_conns.c \
+	commands/list_certs.c \
+	commands/list_pools.c \
+	commands/load_conns.c \
+	commands/load_creds.c \
+	commands/load_pools.c \
+	commands/log.c \
+	commands/version.c \
+	commands/stats.c \
+	swanctl.c swanctl.h
+
+swanctl_LDADD = \
+	$(top_builddir)/src/libcharon/plugins/vici/libvici.la \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la
+
+swanctl.o :		$(top_builddir)/config.status
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon/plugins/vici \
+	-DSWANCTLDIR=\""${swanctldir}\"" \
+	-DPLUGINS=\""${s_plugins}\""
+
+man_MANS = \
+	swanctl.8 \
+	swanctl.conf.5
+
+BUILT_SOURCES = swanctl.conf swanctl.conf.5.main
+EXTRA_DIST = swanctl.opt swanctl.conf swanctl.conf.5.main
+CLEANFILES = $(man_MANS)
+
+.opt.conf:
+	$(AM_V_GEN) \
+	$(PYTHON) $(top_srcdir)/conf/format-options.py -n -f conf $< > $(srcdir)/$@
+
+swanctl.conf.5.main: swanctl.opt
+	$(AM_V_GEN) \
+	$(PYTHON) $(top_srcdir)/conf/format-options.py -n -f man $< > $(srcdir)/$@
+
+swanctl.conf.5: swanctl.conf.5.head swanctl.conf.5.main swanctl.conf.5.tail
+	$(AM_V_GEN) \
+	cat swanctl.conf.5.head $(srcdir)/swanctl.conf.5.main swanctl.conf.5.tail > $@
+
+maintainer-clean-local:
+	cd $(srcdir) && rm -f swanctl.conf swanctl.conf.5.main
+
+install-data-local: swanctl.conf
+	test -e "$(DESTDIR)$(swanctldir)" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)"
+	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)/x509crl" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509crl" || true
+	test -e "$(DESTDIR)$(swanctldir)/x509ac" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ac" || 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)/pkcs8" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs8" || 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
new file mode 100644
index 0000000..1491597
--- /dev/null
+++ b/src/swanctl/Makefile.in
@@ -0,0 +1,981 @@
+# 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@
+sbin_PROGRAMS = swanctl$(EXEEXT)
+subdir = src/swanctl
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+	$(srcdir)/swanctl.8.in $(srcdir)/swanctl.conf.5.head.in \
+	$(srcdir)/swanctl.conf.5.tail.in $(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 = swanctl.8 swanctl.conf.5.head swanctl.conf.5.tail
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" \
+	"$(DESTDIR)$(man8dir)"
+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/list_conns.$(OBJEXT) commands/list_certs.$(OBJEXT) \
+	commands/list_pools.$(OBJEXT) commands/load_conns.$(OBJEXT) \
+	commands/load_creds.$(OBJEXT) commands/load_pools.$(OBJEXT) \
+	commands/log.$(OBJEXT) commands/version.$(OBJEXT) \
+	commands/stats.$(OBJEXT) swanctl.$(OBJEXT)
+swanctl_OBJECTS = $(am_swanctl_OBJECTS)
+swanctl_DEPENDENCIES =  \
+	$(top_builddir)/src/libcharon/plugins/vici/libvici.la \
+	$(top_builddir)/src/libstrongswan/libstrongswan.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 = 
+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 = $(swanctl_SOURCES)
+DIST_SOURCES = $(swanctl_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+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; }; \
+  }
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+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@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+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@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+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@
+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@
+swanctl_SOURCES = \
+	command.c command.h \
+	commands/initiate.c \
+	commands/terminate.c \
+	commands/install.c \
+	commands/list_sas.c \
+	commands/list_pols.c \
+	commands/list_conns.c \
+	commands/list_certs.c \
+	commands/list_pools.c \
+	commands/load_conns.c \
+	commands/load_creds.c \
+	commands/load_pools.c \
+	commands/log.c \
+	commands/version.c \
+	commands/stats.c \
+	swanctl.c swanctl.h
+
+swanctl_LDADD = \
+	$(top_builddir)/src/libcharon/plugins/vici/libvici.la \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan \
+	-I$(top_srcdir)/src/libcharon/plugins/vici \
+	-DSWANCTLDIR=\""${swanctldir}\"" \
+	-DPLUGINS=\""${s_plugins}\""
+
+man_MANS = \
+	swanctl.8 \
+	swanctl.conf.5
+
+BUILT_SOURCES = swanctl.conf swanctl.conf.5.main
+EXTRA_DIST = swanctl.opt swanctl.conf swanctl.conf.5.main
+CLEANFILES = $(man_MANS)
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .conf .lo .o .obj .opt
+$(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/swanctl/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/swanctl/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):
+swanctl.8: $(top_builddir)/config.status $(srcdir)/swanctl.8.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+swanctl.conf.5.head: $(top_builddir)/config.status $(srcdir)/swanctl.conf.5.head.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+swanctl.conf.5.tail: $(top_builddir)/config.status $(srcdir)/swanctl.conf.5.tail.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	 || test -f $$p1 \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	    echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+	    $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+	@list='$(sbin_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
+commands/$(am__dirstamp):
+	@$(MKDIR_P) commands
+	@: > commands/$(am__dirstamp)
+commands/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) commands/$(DEPDIR)
+	@: > commands/$(DEPDIR)/$(am__dirstamp)
+commands/initiate.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/terminate.$(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) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/list_pols.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/list_conns.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/list_certs.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/list_pools.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/load_conns.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/load_creds.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/load_pools.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/log.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/version.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+commands/stats.$(OBJEXT): commands/$(am__dirstamp) \
+	commands/$(DEPDIR)/$(am__dirstamp)
+
+swanctl$(EXEEXT): $(swanctl_OBJECTS) $(swanctl_DEPENDENCIES) $(EXTRA_swanctl_DEPENDENCIES) 
+	@rm -f swanctl$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(swanctl_OBJECTS) $(swanctl_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+	-rm -f commands/*.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/command.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/swanctl.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/initiate.Po at am__quote@
+ at 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_certs.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_conns.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_pols.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_pools.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/list_sas.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/load_conns.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/load_creds.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/load_pools.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/log.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/stats.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/terminate.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at commands/$(DEPDIR)/version.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 $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-man5: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man5dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.5[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man5:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man5dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.5[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
+install-man8: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man8dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.8[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man8:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man8dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.8[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+
+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: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+	for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) 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:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+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 commands/$(DEPDIR)/$(am__dirstamp)
+	-rm -f commands/$(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."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR) commands/$(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-data-local install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man5 install-man8
+
+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) commands/$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+	maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man5 uninstall-man8
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-sbinPROGRAMS 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-data-local install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-man5 \
+	install-man8 install-pdf install-pdf-am install-ps \
+	install-ps-am install-sbinPROGRAMS install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic maintainer-clean-local mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+	uninstall-man uninstall-man5 uninstall-man8 \
+	uninstall-sbinPROGRAMS
+
+
+swanctl.o :		$(top_builddir)/config.status
+
+.opt.conf:
+	$(AM_V_GEN) \
+	$(PYTHON) $(top_srcdir)/conf/format-options.py -n -f conf $< > $(srcdir)/$@
+
+swanctl.conf.5.main: swanctl.opt
+	$(AM_V_GEN) \
+	$(PYTHON) $(top_srcdir)/conf/format-options.py -n -f man $< > $(srcdir)/$@
+
+swanctl.conf.5: swanctl.conf.5.head swanctl.conf.5.main swanctl.conf.5.tail
+	$(AM_V_GEN) \
+	cat swanctl.conf.5.head $(srcdir)/swanctl.conf.5.main swanctl.conf.5.tail > $@
+
+maintainer-clean-local:
+	cd $(srcdir) && rm -f swanctl.conf swanctl.conf.5.main
+
+install-data-local: swanctl.conf
+	test -e "$(DESTDIR)$(swanctldir)" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)"
+	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)/x509crl" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509crl" || true
+	test -e "$(DESTDIR)$(swanctldir)/x509ac" || $(INSTALL) -d "$(DESTDIR)$(swanctldir)/x509ac" || 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)/pkcs8" || $(INSTALL) -d -m 750 "$(DESTDIR)$(swanctldir)/pkcs8" || true
+	test -e "$(DESTDIR)$(swanctldir)/swanctl.conf" || $(INSTALL) -m 640 $(srcdir)/swanctl.conf $(DESTDIR)$(swanctldir)/swanctl.conf || true
+
+# 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/swanctl/command.c b/src/swanctl/command.c
new file mode 100644
index 0000000..e488273
--- /dev/null
+++ b/src/swanctl/command.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include "command.h"
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <library.h>
+#include <utils/debug.h>
+#include <utils/optionsfrom.h>
+
+/**
+ * Registered commands.
+ */
+static command_t cmds[MAX_COMMANDS];
+
+/**
+ * active command.
+ */
+static int active = 0;
+
+/**
+ * number of registered commands
+ */
+static int registered = 0;
+
+/**
+ * help command index
+ */
+static int help_idx;
+
+/**
+ * Uri to connect to
+ */
+static char *uri = NULL;
+
+static int argc;
+
+static char **argv;
+
+static options_t *options;
+
+/**
+ * Global options used by all subcommands
+ */
+static struct option command_opts[MAX_COMMANDS > MAX_OPTIONS ?
+									MAX_COMMANDS : MAX_OPTIONS];
+
+/**
+ * Global optstring used by all subcommands
+ */
+static char command_optstring[(MAX_COMMANDS > MAX_OPTIONS ?
+								MAX_COMMANDS : MAX_OPTIONS) * 3];
+
+/**
+ * Build command_opts/command_optstr for the active command
+ */
+static void build_opts()
+{
+	int i, pos = 0;
+
+	memset(command_opts, 0, sizeof(command_opts));
+	memset(command_optstring, 0, sizeof(command_optstring));
+	if (active == help_idx)
+	{
+		for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
+		{
+			command_opts[i].name = cmds[i].cmd;
+			command_opts[i].val = cmds[i].op;
+			command_optstring[i] = cmds[i].op;
+		}
+	}
+	else
+	{
+		for (i = 0; cmds[active].options[i].name; i++)
+		{
+			command_opts[i].name = cmds[active].options[i].name;
+			command_opts[i].has_arg = cmds[active].options[i].arg;
+			command_opts[i].val = cmds[active].options[i].op;
+			command_optstring[pos++] = cmds[active].options[i].op;
+			switch (cmds[active].options[i].arg)
+			{
+				case optional_argument:
+					command_optstring[pos++] = ':';
+					/* FALL */
+				case required_argument:
+					command_optstring[pos++] = ':';
+					/* FALL */
+				case no_argument:
+				default:
+					break;
+			}
+		}
+	}
+}
+
+/**
+ * getopt_long wrapper
+ */
+int command_getopt(char **arg)
+{
+	int op;
+
+	while (TRUE)
+	{
+		op = getopt_long(argc, argv, command_optstring, command_opts, NULL);
+		switch (op)
+		{
+			case '+':
+				if (!options->from(options, optarg, &argc, &argv, optind))
+				{
+					/* a error value */
+					return 255;
+				}
+				continue;
+			case 'v':
+				dbg_default_set_level(atoi(optarg));
+				continue;
+			case 'u':
+				uri = optarg;
+				continue;
+			default:
+				*arg = optarg;
+				return op;
+		}
+	}
+}
+
+/**
+ * Register a command
+ */
+void command_register(command_t command)
+{
+	int i;
+
+	if (registered == MAX_COMMANDS)
+	{
+		fprintf(stderr, "unable to register command, please increase "
+				"MAX_COMMANDS\n");
+		return;
+	}
+
+	cmds[registered] = command;
+	/* append default options, but not to --help */
+	if (!active)
+	{
+		for (i = 0; i < countof(cmds[registered].options) - 1; i++)
+		{
+			if (!cmds[registered].options[i].name)
+			{
+				break;
+			}
+		}
+		if (i > countof(cmds[registered].options) - 3)
+		{
+			fprintf(stderr, "command '%s' registered too many options, please "
+					"increase MAX_OPTIONS\n", command.cmd);
+		}
+		else
+		{
+			cmds[registered].options[i++] = (command_option_t) {
+				"debug",	'v', 1, "set debug level, default: 1"
+			};
+			cmds[registered].options[i++] = (command_option_t) {
+				"options",	'+', 1, "read command line options from file"
+			};
+			cmds[registered].options[i++] = (command_option_t) {
+				"uri",		'u', 1, "service URI to connect to"
+			};
+		}
+	}
+	registered++;
+}
+
+/**
+ * Print usage text, with an optional error
+ */
+int command_usage(char *error, ...)
+{
+	va_list args;
+	FILE *out = stdout;
+	int i;
+
+	if (error)
+	{
+		out = stderr;
+		fprintf(out, "Error: ");
+		va_start(args, error);
+		vfprintf(out, error, args);
+		va_end(args);
+		fprintf(out, "\n");
+	}
+	fprintf(out, "strongSwan %s swanctl\n", VERSION);
+
+	if (active == help_idx)
+	{
+		fprintf(out, "loaded plugins: %s\n",
+				lib->plugins->loaded_plugins(lib->plugins));
+	}
+
+	fprintf(out, "usage:\n");
+	if (active == help_idx)
+	{
+		for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
+		{
+			fprintf(out, "  swanctl --%-10s (-%c)  %s\n",
+					cmds[i].cmd, cmds[i].op, cmds[i].description);
+		}
+	}
+	else
+	{
+		for (i = 0; cmds[active].line[i]; i++)
+		{
+			if (i == 0)
+			{
+				fprintf(out, "  swanctl --%s %s\n",
+						cmds[active].cmd, cmds[active].line[i]);
+			}
+			else
+			{
+				fprintf(out, "                 %s\n", cmds[active].line[i]);
+			}
+		}
+		for (i = 0; cmds[active].options[i].name; i++)
+		{
+			fprintf(out, "           --%-15s (-%c)  %s\n",
+					cmds[active].options[i].name, cmds[active].options[i].op,
+					cmds[active].options[i].desc);
+		}
+	}
+	return error != NULL;
+}
+
+/**
+ * Dispatch cleanup hook
+ */
+static void cleanup()
+{
+	options->destroy(options);
+}
+
+/**
+ * Open vici connection, call a command
+ */
+static int call_command(command_t *cmd)
+{
+	vici_conn_t *conn;
+	int ret;
+
+	conn = vici_connect(uri);
+	if (!conn)
+	{
+		command_usage("connecting to '%s' URI failed: %s",
+					  uri ?: "default", strerror(errno));
+		return errno;
+	}
+	ret = cmd->call(conn);
+	vici_disconnect(conn);
+	return ret;
+}
+
+/**
+ * Dispatch commands.
+ */
+int command_dispatch(int c, char *v[])
+{
+	int op, i;
+
+	options = options_create();
+	atexit(cleanup);
+	active = help_idx = registered;
+	argc = c;
+	argv = v;
+	command_register((command_t){NULL, 'h', "help", "show usage information"});
+
+	build_opts();
+	op = getopt_long(c, v, command_optstring, command_opts, NULL);
+	for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
+	{
+		if (cmds[i].op == op)
+		{
+			active = i;
+			build_opts();
+			if (help_idx == i)
+			{
+				return command_usage(NULL);
+			}
+			return call_command(&cmds[i]);
+		}
+	}
+	return command_usage(c > 1 ? "invalid operation" : NULL);
+}
diff --git a/src/swanctl/command.h b/src/swanctl/command.h
new file mode 100644
index 0000000..8510fa4
--- /dev/null
+++ b/src/swanctl/command.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 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 command command
+ * @{ @ingroup swanctl
+ */
+
+#ifndef COMMAND_H_
+#define COMMAND_H_
+
+#include <libvici.h>
+#include <library.h>
+
+/**
+ * Maximum number of commands (+1).
+ */
+#define MAX_COMMANDS 16
+
+/**
+ * Maximum number of options in a command (+3)
+ */
+#define MAX_OPTIONS 32
+
+/**
+ * Maximum number of usage summary lines (+1)
+ */
+#define MAX_LINES 10
+
+typedef struct command_t command_t;
+typedef struct command_option_t command_option_t;
+typedef enum command_format_options_t command_format_options_t;
+
+/**
+ * Option specification
+ */
+struct command_option_t {
+	/** long option string of the option */
+	char *name;
+	/** short option character of the option */
+	char op;
+	/** expected argument to option, no/req/opt_argument */
+	int arg;
+	/** description of the option */
+	char *desc;
+};
+
+/**
+ * Command specification.
+ */
+struct command_t {
+	/** Function implementing the command */
+	int (*call)(vici_conn_t *conn);
+	/** short option character */
+	char op;
+	/** long option string */
+	char *cmd;
+	/** description of the command */
+	char *description;
+	/** usage summary of the command */
+	char *line[MAX_LINES];
+	/** list of options the command accepts */
+	command_option_t options[MAX_OPTIONS];
+};
+
+/**
+ * Command format options
+*/
+enum command_format_options_t {
+	COMMAND_FORMAT_NONE   = 0,
+	COMMAND_FORMAT_RAW    = (1<<0),
+	COMMAND_FORMAT_PRETTY = (1<<1),
+	COMMAND_FORMAT_PEM    = (1<<2),
+};
+
+/**
+ * Get the next option, as with getopt.
+ */
+int command_getopt(char **arg);
+
+/**
+ * Register a command.
+ */
+void command_register(command_t command);
+
+/**
+ * Dispatch commands.
+ */
+int command_dispatch(int argc, char *argv[]);
+
+/**
+ * Show usage information of active command.
+ */
+int command_usage(char *error, ...);
+
+#endif /** COMMAND_H_ @}*/
diff --git a/src/swanctl/commands/initiate.c b/src/swanctl/commands/initiate.c
new file mode 100644
index 0000000..080dc41
--- /dev/null
+++ b/src/swanctl/commands/initiate.c
@@ -0,0 +1,132 @@
+/*
+ * 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 "command.h"
+
+#include <errno.h>
+
+CALLBACK(log_cb, void,
+	command_format_options_t *format, char *name, vici_res_t *msg)
+{
+	if (*format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(msg, "log", *format & COMMAND_FORMAT_PRETTY, stdout);
+	}
+	else
+	{
+		printf("[%s] %s\n",
+			   vici_find_str(msg, "   ", "group"),
+			   vici_find_str(msg, "", "msg"));
+	}
+}
+
+static int initiate(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg, *child = NULL;
+	int ret = 0, timeout = 0, level = 1;
+
+	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 'c':
+				child = arg;
+				continue;
+			case 't':
+				timeout = atoi(arg);
+				continue;
+			case 'l':
+				level = atoi(arg);
+				continue;
+			case EOF:
+				break;
+			default:
+				return command_usage("invalid --initiate option");
+		}
+		break;
+	}
+
+	if (vici_register(conn, "control-log", log_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for log failed: %s\n", strerror(errno));
+		return errno;
+	}
+	req = vici_begin("initiate");
+	if (child)
+	{
+		vici_add_key_valuef(req, "child", "%s", child);
+	}
+	if (timeout)
+	{
+		vici_add_key_valuef(req, "timeout", "%d", timeout * 1000);
+	}
+	vici_add_key_valuef(req, "loglevel", "%d", level);
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "initiate request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "initiate reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		if (streq(vici_find_str(res, "no", "success"), "yes"))
+		{
+			printf("initiate completed successfully\n");
+		}
+		else
+		{
+			fprintf(stderr, "initiate 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) {
+		initiate, 'i', "initiate", "initiate a connection",
+		{"--child <name> [--timeout <s>] [--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"child",		'c', 1, "initate a CHILD_SA configuration"},
+			{"timeout",		't', 1, "timeout in seconds before detaching"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+			{"loglevel",	'l', 1, "verbosity of redirected log"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/install.c b/src/swanctl/commands/install.c
new file mode 100644
index 0000000..e8727d5
--- /dev/null
+++ b/src/swanctl/commands/install.c
@@ -0,0 +1,125 @@
+/*
+ * 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 "command.h"
+
+#include <errno.h>
+
+static int manage_policy(vici_conn_t *conn, char *label)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg, *child = NULL;
+	int ret = 0;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 'P':
+				format |= COMMAND_FORMAT_RAW;
+				/* fall through to raw */
+			case 'r':
+				format |= COMMAND_FORMAT_PRETTY;
+				continue;
+			case 'c':
+				child = arg;
+				continue;
+			case EOF:
+				break;
+			default:
+				return command_usage("invalid --%s option", label);
+		}
+		break;
+	}
+	req = vici_begin(label);
+	if (child)
+	{
+		vici_add_key_valuef(req, "child", "%s", child);
+	}
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "%s request failed: %s\n", label, strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		puts(label);
+		vici_dump(res, " reply", format & COMMAND_FORMAT_PRETTY, stdout);
+	}
+	else
+	{
+		if (streq(vici_find_str(res, "no", "success"), "yes"))
+		{
+			printf("%s completed successfully\n", label);
+		}
+		else
+		{
+			fprintf(stderr, "%s failed: %s\n",
+					label, vici_find_str(res, "", "errmsg"));
+			ret = 1;
+		}
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+static int uninstall(vici_conn_t *conn)
+{
+	return manage_policy(conn, "uninstall");
+}
+
+static int install(vici_conn_t *conn)
+{
+	return manage_policy(conn, "install");
+}
+
+/**
+ * Register the uninstall command.
+ */
+static void __attribute__ ((constructor))reg_uninstall()
+{
+	command_register((command_t) {
+		uninstall, 'u', "uninstall", "uninstall a trap or shunt policy",
+		{"--child <name> [--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"child",		'c', 1, "CHILD_SA configuration to uninstall"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
+
+/**
+ * Register install the command.
+ */
+static void __attribute__ ((constructor))reg_install()
+{
+	command_register((command_t) {
+		install, 'p', "install", "install a trap or shunt policy",
+		{"--child <name> [--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"child",		'c', 1, "CHILD_SA configuration to install"},
+			{"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
new file mode 100644
index 0000000..bee5fda
--- /dev/null
+++ b/src/swanctl/commands/list_certs.c
@@ -0,0 +1,670 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <time.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 "command.h"
+
+/**
+ * Print PEM encoding of a certificate
+ */
+static void print_pem(certificate_t *cert)
+{
+	chunk_t encoding;
+
+	if (cert->get_encoding(cert, CERT_PEM, &encoding))
+	{
+		printf("%.*s", (int)encoding.len, encoding.ptr);
+		free(encoding.ptr);
+	}
+	else
+	{
+		fprintf(stderr, "PEM encoding certificate failed\n");
+	}
+}
+
+/**
+ * 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)
+{
+	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);
+
+	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("groups:    ");
+			first = FALSE;
+		}
+		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;
+		}
+		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);
+	}
+	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");
+		}
+	}
+}
+
+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;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 's':
+				subject = arg;
+				continue;
+			case 't':
+				type = arg;
+				continue;
+			case 'p':
+				format |= COMMAND_FORMAT_PEM;
+				continue;
+			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-certs option");
+		}
+		break;
+	}
+	if (vici_register(conn, "list-cert", list_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for certificates failed: %s\n",
+				strerror(errno));
+		return errno;
+	}
+	req = vici_begin("list-certs");
+	if (type)
+	{
+		vici_add_key_valuef(req, "type", "%s", type);
+	}
+	if (subject)
+	{
+		vici_add_key_valuef(req, "subject", "%s", subject);
+	}
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "list-certs request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "list-certs reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	vici_free_res(res);
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+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]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"subject",		's', 1, "filter by certificate subject"},
+			{"type",		't', 1, "filter by certificate type"},
+			{"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"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/list_conns.c b/src/swanctl/commands/list_conns.c
new file mode 100644
index 0000000..ec5da4b
--- /dev/null
+++ b/src/swanctl/commands/list_conns.c
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+
+#include "command.h"
+
+#include <collections/hashtable.h>
+
+/**
+ * Free hashtable with contained strings
+ */
+static void free_hashtable(hashtable_t *hashtable)
+{
+	enumerator_t *enumerator;
+	char *str;
+
+	enumerator = hashtable->create_enumerator(hashtable);
+	while (enumerator->enumerate(enumerator, NULL, &str))
+	{
+		free(str);
+	}
+	enumerator->destroy(enumerator);
+
+	hashtable->destroy(hashtable);
+}
+
+CALLBACK(values, int,
+	hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
+{
+	chunk_t chunk;
+	char *str;
+
+	chunk = chunk_create(value, len);
+	if (chunk_printable(chunk, NULL, ' '))
+	{
+		if (asprintf(&str, "%.*s", len, value) >= 0)
+		{
+			free(sa->put(sa, name, str));
+		}
+	}
+	return 0;
+}
+
+
+CALLBACK(list, int,
+	hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
+{
+	chunk_t chunk;
+	char *str;
+
+	chunk = chunk_create(value, len);
+	if (chunk_printable(chunk, NULL, ' '))
+	{
+		str = sa->get(sa, name);
+		if (asprintf(&str, "%s%s%.*s",
+					 str ?: "", str ? " " : "", len, value) >= 0)
+		{
+			free(sa->put(sa, name, str));
+		}
+	}
+	return 0;
+}
+
+CALLBACK(children_sn, int,
+	hashtable_t *ike, vici_res_t *res, char *name)
+{
+	hashtable_t *child;
+	int ret;
+
+	child = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
+	ret = vici_parse_cb(res, NULL, values, list, child);
+	if (ret == 0)
+	{
+		printf("  %s: %s\n", name, child->get(child, "mode"));
+		printf("    local:  %s\n", child->get(child, "local-ts"));
+		printf("    remote: %s\n", child->get(child, "remote-ts"));
+	}
+	free_hashtable(child);
+	return ret;
+}
+
+CALLBACK(conn_sn, int,
+	hashtable_t *ike, vici_res_t *res, char *name)
+{
+	int ret = 0;
+
+	if (streq(name, "children"))
+	{
+		return vici_parse_cb(res, children_sn, NULL, NULL, NULL);
+	}
+	if (streq(name, "local") || streq(name, "remote"))
+	{
+		hashtable_t *auth;
+
+		auth = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
+		ret = vici_parse_cb(res, NULL, values, list, auth);
+		if (ret == 0)
+		{
+			printf("  %s %s authentication:\n",
+				name, auth->get(auth, "class") ?: "unspecified");
+			if (auth->get(auth, "id"))
+			{
+				printf("    id: %s\n", auth->get(auth, "id"));
+			}
+			if (auth->get(auth, "groups"))
+			{
+				printf("    groups: %s\n", auth->get(auth, "groups"));
+			}
+			if (auth->get(auth, "certs"))
+			{
+				printf("    certs: %s\n", auth->get(auth, "certs"));
+			}
+			if (auth->get(auth, "cacerts"))
+			{
+				printf("    cacerts: %s\n", auth->get(auth, "cacerts"));
+			}
+		}
+		free_hashtable(auth);
+	}
+	return ret;
+}
+
+CALLBACK(conn_list, int,
+	hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
+{
+	if (chunk_printable(chunk_create(value, len), NULL, ' '))
+	{
+		if (streq(name, "local_addrs"))
+		{
+			printf("  local:  %.*s\n", len, value);
+		}
+		if (streq(name, "remote_addrs"))
+		{
+			printf("  remote: %.*s\n", len, value);
+		}
+	}
+	return 0;
+}
+
+CALLBACK(conns, int,
+	void *null, vici_res_t *res, char *name)
+{
+	printf("%s: %s\n", name, vici_find_str(res, "", "%s.version", name));
+
+	return vici_parse_cb(res, conn_sn, NULL, conn_list, NULL);
+}
+
+CALLBACK(list_cb, void,
+	command_format_options_t *format, char *name, vici_res_t *res)
+{
+	if (*format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "list-conn event", *format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		if (vici_parse_cb(res, conns, NULL, NULL, NULL) != 0)
+		{
+			fprintf(stderr, "parsing conn event failed: %s\n", strerror(errno));
+		}
+	}
+}
+
+static int list_conns(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg;
+
+	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-conns option");
+		}
+		break;
+	}
+	if (vici_register(conn, "list-conn", list_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for connections failed: %s\n",
+				strerror(errno));
+		return errno;
+	}
+	req = vici_begin("list-conns");
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "list-conns request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "list-conns reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	vici_free_res(res);
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		list_conns, 'L', "list-conns", "list loaded configurations",
+		{"[--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_pols.c b/src/swanctl/commands/list_pols.c
new file mode 100644
index 0000000..2317b25
--- /dev/null
+++ b/src/swanctl/commands/list_pols.c
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+
+#include "command.h"
+
+#include <collections/hashtable.h>
+
+/**
+ * Free hashtable with contained strings
+ */
+static void free_hashtable(hashtable_t *hashtable)
+{
+	enumerator_t *enumerator;
+	char *str;
+
+	enumerator = hashtable->create_enumerator(hashtable);
+	while (enumerator->enumerate(enumerator, NULL, &str))
+	{
+		free(str);
+	}
+	enumerator->destroy(enumerator);
+
+	hashtable->destroy(hashtable);
+}
+
+CALLBACK(policy_values, int,
+	hashtable_t *pol, vici_res_t *res, char *name, void *value, int len)
+{
+	chunk_t chunk;
+	char *str;
+
+	chunk = chunk_create(value, len);
+	if (chunk_printable(chunk, NULL, ' '))
+	{
+		if (asprintf(&str, "%.*s", len, value) >= 0)
+		{
+			free(pol->put(pol, name, str));
+		}
+	}
+	return 0;
+}
+
+CALLBACK(policy_list, int,
+	hashtable_t *pol, vici_res_t *res, char *name, void *value, int len)
+{
+	chunk_t chunk;
+	char *str;
+
+	chunk = chunk_create(value, len);
+	if (chunk_printable(chunk, NULL, ' '))
+	{
+		str = pol->get(pol, name);
+		if (asprintf(&str, "%s%s%.*s",
+					 str ?: "", str ? " " : "", len, value) >= 0)
+		{
+			free(pol->put(pol, name, str));
+		}
+	}
+	return 0;
+}
+
+CALLBACK(policies, int,
+	void *null, vici_res_t *res, char *name)
+{
+	hashtable_t *pol;
+	int ret;
+
+	pol = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
+	ret = vici_parse_cb(res, NULL, policy_values, policy_list, pol);
+
+	printf("%s, %s\n", name, pol->get(pol, "mode"));
+	printf("  local:  %s\n", pol->get(pol, "local-ts"));
+	printf("  remote: %s\n", pol->get(pol, "remote-ts"));
+
+	free_hashtable(pol);
+	return ret;
+}
+
+CALLBACK(list_cb, void,
+	command_format_options_t *format, char *name, vici_res_t *res)
+{
+	if (*format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "list-policy event", *format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		if (vici_parse_cb(res, policies, NULL, NULL, NULL) != 0)
+		{
+			fprintf(stderr, "parsing policy event failed: %s\n", strerror(errno));
+		}
+	}
+}
+
+static int list_pols(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool trap = FALSE, drop = FALSE, pass = FALSE;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg, *child = NULL;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 'c':
+				child = arg;
+				continue;
+			case 't':
+				trap = TRUE;
+				continue;
+			case 'd':
+				drop = TRUE;
+				continue;
+			case 'p':
+				pass = TRUE;
+				continue;
+			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-pols option");
+		}
+		break;
+	}
+	if (!trap && !drop && !pass)
+	{
+		trap = drop = pass = TRUE;
+	}
+	if (vici_register(conn, "list-policy", list_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for policies failed: %s\n",
+				strerror(errno));
+		return errno;
+	}
+	req = vici_begin("list-policies");
+	if (child)
+	{
+		vici_add_key_valuef(req, "child", "%s", child);
+	}
+	if (trap)
+	{
+		vici_add_key_valuef(req, "trap", "yes");
+	}
+	if (drop)
+	{
+		vici_add_key_valuef(req, "drop", "yes");
+	}
+	if (pass)
+	{
+		vici_add_key_valuef(req, "pass", "yes");
+	}
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "list-policies request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "list-policies reply", format & COMMAND_FORMAT_PRETTY, stdout);
+	}
+	vici_free_res(res);
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		list_pols, 'P', "list-pols", "list currently installed policies",
+		{"[--child <name>] [--trap] [--drop] [--pass] [--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"child",		'c', 1, "filter policies by CHILD_SA config name"},
+			{"trap",		't', 0, "list trap policies"},
+			{"drop",		'd', 0, "list drop policies"},
+			{"pass",		'p', 0, "list bypass policies"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/list_pools.c b/src/swanctl/commands/list_pools.c
new file mode 100644
index 0000000..17ea539
--- /dev/null
+++ b/src/swanctl/commands/list_pools.c
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+
+#include "command.h"
+
+CALLBACK(list_pool, int,
+	linked_list_t *list, vici_res_t *res, char *name)
+{
+	char pool[64], leases[32];
+
+	snprintf(pool, sizeof(pool), "%s:", name);
+	snprintf(leases, sizeof(leases), "%s / %s / %s",
+		vici_find_str(res, "", "%s.online", name),
+		vici_find_str(res, "", "%s.offline", name),
+		vici_find_str(res, "", "%s.size", name));
+
+	printf("%-20s %-30s %16s\n",
+		name, vici_find_str(res, "", "%s.base", name), leases);
+
+	return 0;
+}
+
+static int list_pools(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg;
+	int ret = 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 EOF:
+				break;
+			default:
+				return command_usage("invalid --list-pools option");
+		}
+		break;
+	}
+
+	req = vici_begin("get-pools");
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "get-pools request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "get-pools reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		ret = vici_parse_cb(res, list_pool, NULL, NULL, NULL);
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		list_pools, 'A', "list-pools", "list loaded pool configurations",
+		{"[--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_sas.c b/src/swanctl/commands/list_sas.c
new file mode 100644
index 0000000..80c279c
--- /dev/null
+++ b/src/swanctl/commands/list_sas.c
@@ -0,0 +1,366 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+
+#include "command.h"
+
+#include <collections/hashtable.h>
+
+/**
+ * Free hashtable with contained strings
+ */
+static void free_hashtable(hashtable_t *hashtable)
+{
+	enumerator_t *enumerator;
+	char *str;
+
+	enumerator = hashtable->create_enumerator(hashtable);
+	while (enumerator->enumerate(enumerator, NULL, &str))
+	{
+		free(str);
+	}
+	enumerator->destroy(enumerator);
+
+	hashtable->destroy(hashtable);
+}
+
+CALLBACK(sa_values, int,
+	hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
+{
+	chunk_t chunk;
+	char *str;
+
+	chunk = chunk_create(value, len);
+	if (chunk_printable(chunk, NULL, ' '))
+	{
+		if (asprintf(&str, "%.*s", len, value) >= 0)
+		{
+			free(sa->put(sa, name, str));
+		}
+	}
+	return 0;
+}
+
+
+CALLBACK(sa_list, int,
+	hashtable_t *sa, vici_res_t *res, char *name, void *value, int len)
+{
+	chunk_t chunk;
+	char *str;
+
+	chunk = chunk_create(value, len);
+	if (chunk_printable(chunk, NULL, ' '))
+	{
+		str = sa->get(sa, name);
+		if (asprintf(&str, "%s%s%.*s",
+					 str ?: "", str ? " " : "", len, value) >= 0)
+		{
+			free(sa->put(sa, name, str));
+		}
+	}
+	return 0;
+}
+
+CALLBACK(child_sas, int,
+	hashtable_t *ike, vici_res_t *res, char *name)
+{
+	hashtable_t *child;
+	int ret;
+
+	child = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
+	ret = vici_parse_cb(res, NULL, sa_values, sa_list, child);
+	if (ret == 0)
+	{
+		printf("  %s: #%s, %s, %s%s, %s:",
+			name, child->get(child, "reqid"),
+			child->get(child, "state"), child->get(child, "mode"),
+			child->get(child, "encap") ? "-in-UDP" : "",
+			child->get(child, "protocol"));
+
+		if (child->get(child, "encr-alg"))
+		{
+			printf("%s", child->get(child, "encr-alg"));
+			if (child->get(child, "encr-keysize"))
+			{
+				printf("-%s", child->get(child, "encr-keysize"));
+			}
+		}
+		if (child->get(child, "integ-alg"))
+		{
+			if (child->get(child, "encr-alg"))
+			{
+				printf("/");
+			}
+			printf("%s", child->get(child, "integ-alg"));
+			if (child->get(child, "integ-keysize"))
+			{
+				printf("-%s", child->get(child, "integ-keysize"));
+			}
+		}
+		if (child->get(child, "prf-alg"))
+		{
+			printf("/%s", child->get(child, "prf-alg"));
+		}
+		if (child->get(child, "dh-group"))
+		{
+			printf("/%s", child->get(child, "dh-group"));
+		}
+		if (child->get(child, "esn"))
+		{
+			printf("/%s", child->get(child, "esn"));
+		}
+		printf("\n");
+
+		printf("    installed %s ago", child->get(child, "install-time"));
+		if (child->get(child, "rekey-time"))
+		{
+			printf(", rekeying in %ss", child->get(child, "rekey-time"));
+		}
+		if (child->get(child, "life-time"))
+		{
+			printf(", expires in %ss", child->get(child, "life-time"));
+		}
+		printf("\n");
+
+		printf("    in  %s%s%s", child->get(child, "spi-in"),
+			child->get(child, "cpi-in") ? "/" : "",
+			child->get(child, "cpi-in") ?: "");
+		printf(", %6s bytes, %5s packets",
+			child->get(child, "bytes-in"), child->get(child, "packets-in"));
+		if (child->get(child, "use-in"))
+		{
+			printf(", %5ss ago", child->get(child, "use-in"));
+		}
+		printf("\n");
+
+		printf("    out %s%s%s", child->get(child, "spi-out"),
+			child->get(child, "cpi-out") ? "/" : "",
+			child->get(child, "cpi-out") ?: "");
+		printf(", %6s bytes, %5s packets",
+			child->get(child, "bytes-out"), child->get(child, "packets-out"));
+		if (child->get(child, "use-out"))
+		{
+			printf(", %5ss ago", child->get(child, "use-out"));
+		}
+		printf("\n");
+
+		printf("    local  %s\n", child->get(child, "local-ts"));
+		printf("    remote %s\n", child->get(child, "remote-ts"));
+	}
+	free_hashtable(child);
+	return ret;
+}
+
+CALLBACK(ike_sa, int,
+	hashtable_t *ike, vici_res_t *res, char *name)
+{
+	if (streq(name, "child-sas"))
+	{
+		printf("%s: #%s, %s, IKEv%s, %s:%s\n",
+			ike->get(ike, "name"), ike->get(ike, "uniqueid"),
+			ike->get(ike, "state"), ike->get(ike, "version"),
+			ike->get(ike, "initiator-spi"), ike->get(ike, "responder-spi"));
+
+		printf("  local  '%s' @ %s\n",
+			ike->get(ike, "local-id"), ike->get(ike, "local-host"));
+		printf("  remote '%s' @ %s",
+			ike->get(ike, "remote-id"), ike->get(ike, "remote-host"));
+		if (ike->get(ike, "remote-eap-id"))
+		{
+			printf(" EAP: '%s'", ike->get(ike, "remote-eap-id"));
+		}
+		if (ike->get(ike, "remote-xauth-id"))
+		{
+			printf(" XAuth: '%s'", ike->get(ike, "remote-xauth-id"));
+		}
+		printf("\n");
+
+		if (ike->get(ike, "encr-alg"))
+		{
+			printf("  %s", ike->get(ike, "encr-alg"));
+			if (ike->get(ike, "encr-keysize"))
+			{
+				printf("-%s", ike->get(ike, "encr-keysize"));
+			}
+			if (ike->get(ike, "integ-alg"))
+			{
+				printf("/%s", ike->get(ike, "integ-alg"));
+			}
+			if (ike->get(ike, "integ-keysize"))
+			{
+				printf("-%s", ike->get(ike, "integ-keysize"));
+			}
+			printf("/%s", ike->get(ike, "prf-alg"));
+			printf("/%s", ike->get(ike, "dh-group"));
+			printf("\n");
+		}
+
+		if (ike->get(ike, "established"))
+		{
+			printf("  established %ss ago", ike->get(ike, "established"));
+			if (ike->get(ike, "rekey-time"))
+			{
+				printf(", rekeying in %ss", ike->get(ike, "rekey-time"));
+			}
+			if (ike->get(ike, "reauth-time"))
+			{
+				printf(", reauth in %ss", ike->get(ike, "reauth-time"));
+			}
+			if (ike->get(ike, "life-time"))
+			{
+				printf(", expires in %ss", ike->get(ike, "life-time"));
+			}
+			printf("\n");
+		}
+
+		if (ike->get(ike, "tasks-queued"))
+		{
+			printf("  queued:  %s\n", ike->get(ike, "tasks-queued"));
+		}
+		if (ike->get(ike, "tasks-active"))
+		{
+			printf("  active:  %s\n", ike->get(ike, "tasks-active"));
+		}
+		if (ike->get(ike, "tasks-passive"))
+		{
+			printf("  passive: %s\n", ike->get(ike, "tasks-passive"));
+		}
+
+		return vici_parse_cb(res, child_sas, NULL, NULL, ike);
+	}
+	return 0;
+}
+
+CALLBACK(ike_sas, int,
+	void *null, vici_res_t *res, char *name)
+{
+	hashtable_t *ike;
+	int ret;
+
+	ike = hashtable_create(hashtable_hash_str, hashtable_equals_str, 1);
+	ike->put(ike, "name", strdup(name));
+	ret = vici_parse_cb(res, ike_sa, sa_values, sa_list, ike);
+	free_hashtable(ike);
+	return ret;
+}
+
+CALLBACK(list_cb, void,
+	command_format_options_t *format, char *name, vici_res_t *res)
+{
+	if (*format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "list-sa event", *format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		if (vici_parse_cb(res, ike_sas, NULL, NULL, NULL) != 0)
+		{
+			fprintf(stderr, "parsing SA event failed: %s\n", strerror(errno));
+		}
+	}
+}
+
+static int list_sas(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool noblock = FALSE;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg, *ike = NULL;
+	int ike_id = 0;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 'i':
+				ike = arg;
+				continue;
+			case 'I':
+				ike_id = atoi(arg);
+				continue;
+			case 'n':
+				noblock = TRUE;
+				continue;
+			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-sas option");
+		}
+		break;
+	}
+	if (vici_register(conn, "list-sa", list_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for SAs failed: %s\n", strerror(errno));
+		return errno;
+	}
+	req = vici_begin("list-sas");
+	if (ike)
+	{
+		vici_add_key_valuef(req, "ike", "%s", ike);
+	}
+	if (ike_id)
+	{
+		vici_add_key_valuef(req, "ike-id", "%d", ike_id);
+	}
+	if (noblock)
+	{
+		vici_add_key_valuef(req, "noblock", "yes");
+	}
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "list-sas request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "list-sas reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	vici_free_res(res);
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		list_sas, 'l', "list-sas", "list currently active IKE_SAs",
+		{"[--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"ike",			'i', 1, "filter IKE_SAs by name"},
+			{"ike-id",		'I', 1, "filter IKE_SAs by unique identifier"},
+			{"noblock",		'n', 0, "don't wait for IKE_SAs in use"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/load_conns.c b/src/swanctl/commands/load_conns.c
new file mode 100644
index 0000000..7383f7a
--- /dev/null
+++ b/src/swanctl/commands/load_conns.c
@@ -0,0 +1,419 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "command.h"
+#include "swanctl.h"
+
+/**
+ * Check if we should handle a key as a list of comma separated values
+ */
+static bool is_list_key(char *key)
+{
+	char *keys[] = {
+		"local_addrs",
+		"remote_addrs",
+		"proposals",
+		"esp_proposals",
+		"ah_proposals",
+		"local_ts",
+		"remote_ts",
+		"vips",
+		"pools",
+		"groups",
+	};
+	int i;
+
+	for (i = 0; i < countof(keys); i++)
+	{
+		if (strcaseeq(keys[i], key))
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Check if we should handle a key as a list of comma separated files
+ */
+static bool is_file_list_key(char *key)
+{
+	char *keys[] = {
+		"certs",
+		"cacerts",
+	};
+	int i;
+
+	for (i = 0; i < countof(keys); i++)
+	{
+		if (strcaseeq(keys[i], key))
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * Add a vici list from a comma separated string value
+ */
+static void add_list_key(vici_req_t *req, char *key, char *value)
+{
+	enumerator_t *enumerator;
+	char *token;
+
+	vici_begin_list(req, key);
+	enumerator = enumerator_create_token(value, ",", " ");
+	while (enumerator->enumerate(enumerator, &token))
+	{
+		vici_add_list_itemf(req, "%s", token);
+	}
+	enumerator->destroy(enumerator);
+	vici_end_list(req);
+}
+
+/**
+ * Add a vici list of blobs from a comma separated file list
+ */
+static void add_file_list_key(vici_req_t *req, char *key, char *value)
+{
+	enumerator_t *enumerator;
+	chunk_t *map;
+	char *token, buf[PATH_MAX];
+
+	vici_begin_list(req, key);
+	enumerator = enumerator_create_token(value, ",", " ");
+	while (enumerator->enumerate(enumerator, &token))
+	{
+		if (!path_absolute(token))
+		{
+			if (streq(key, "certs"))
+			{
+				snprintf(buf, sizeof(buf), "%s%s%s",
+						 SWANCTL_X509DIR, DIRECTORY_SEPARATOR, token);
+				token = buf;
+			}
+			if (streq(key, "cacerts"))
+			{
+				snprintf(buf, sizeof(buf), "%s%s%s",
+						 SWANCTL_X509CADIR, DIRECTORY_SEPARATOR, token);
+				token = buf;
+			}
+		}
+
+		map = chunk_map(token, FALSE);
+		if (map)
+		{
+			vici_add_list_item(req, map->ptr, map->len);
+			chunk_unmap(map);
+		}
+		else
+		{
+			fprintf(stderr, "loading certificate '%s' failed: %s\n",
+					token, strerror(errno));
+		}
+	}
+	enumerator->destroy(enumerator);
+	vici_end_list(req);
+}
+
+/**
+ * Translate setting key/values from a section into vici key-values/lists
+ */
+static void add_key_values(vici_req_t *req, settings_t *cfg, char *section)
+{
+	enumerator_t *enumerator;
+	char *key, *value;
+
+	enumerator = cfg->create_key_value_enumerator(cfg, section);
+	while (enumerator->enumerate(enumerator, &key, &value))
+	{
+		if (is_list_key(key))
+		{
+			add_list_key(req, key, value);
+		}
+		else if (is_file_list_key(key))
+		{
+			add_file_list_key(req, key, value);
+		}
+		else
+		{
+			vici_add_key_valuef(req, key, "%s", value);
+		}
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Translate a settings section to a vici section
+ */
+static void add_sections(vici_req_t *req, settings_t *cfg, char *section)
+{
+	enumerator_t *enumerator;
+	char *name, buf[256];
+
+	enumerator = cfg->create_section_enumerator(cfg, section);
+	while (enumerator->enumerate(enumerator, &name))
+	{
+		vici_begin_section(req, name);
+		snprintf(buf, sizeof(buf), "%s.%s", section, name);
+		add_key_values(req, cfg, buf);
+		add_sections(req, cfg, buf);
+		vici_end_section(req);
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Load an IKE_SA config with CHILD_SA configs from a section
+ */
+static bool load_conn(vici_conn_t *conn, settings_t *cfg,
+					  char *section, command_format_options_t format)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool ret = TRUE;
+	char buf[128];
+
+	snprintf(buf, sizeof(buf), "%s.%s", "connections", section);
+
+	req = vici_begin("load-conn");
+
+	vici_begin_section(req, section);
+	add_key_values(req, cfg, buf);
+	add_sections(req, cfg, buf);
+	vici_end_section(req);
+
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "load-conn request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "load-conn reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+	{
+		fprintf(stderr, "loading connection '%s' failed: %s\n",
+				section, vici_find_str(res, "", "errmsg"));
+		ret = FALSE;
+	}
+	else
+	{
+		printf("loaded connection '%s'\n", section);
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+CALLBACK(list_conn, int,
+	linked_list_t *list, vici_res_t *res, char *name, void *value, int len)
+{
+	if (streq(name, "conns"))
+	{
+		char *str;
+
+		if (asprintf(&str, "%.*s", len, value) != -1)
+		{
+			list->insert_last(list, str);
+		}
+	}
+	return 0;
+}
+
+/**
+ * Create a list of currently loaded connections
+ */
+static linked_list_t* list_conns(vici_conn_t *conn,
+								 command_format_options_t format)
+{
+	linked_list_t *list;
+	vici_res_t *res;
+
+	list = linked_list_create();
+
+	res = vici_submit(vici_begin("get-conns"), conn);
+	if (res)
+	{
+		if (format & COMMAND_FORMAT_RAW)
+		{
+			vici_dump(res, "get-conns reply", format & COMMAND_FORMAT_PRETTY,
+					  stdout);
+		}
+		vici_parse_cb(res, NULL, NULL, list_conn, list);
+		vici_free_res(res);
+	}
+	return list;
+}
+
+/**
+ * Remove and free a string from a list
+ */
+static void remove_from_list(linked_list_t *list, char *str)
+{
+	enumerator_t *enumerator;
+	char *current;
+
+	enumerator = list->create_enumerator(list);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (streq(current, str))
+		{
+			list->remove_at(list, enumerator);
+			free(current);
+		}
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Unload a connection by name
+ */
+static bool unload_conn(vici_conn_t *conn, char *name,
+					    command_format_options_t format)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool ret = TRUE;
+
+	req = vici_begin("unload-conn");
+	vici_add_key_valuef(req, "name", "%s", name);
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "unload-conn request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "unload-conn reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+	{
+		fprintf(stderr, "unloading connection '%s' failed: %s\n",
+				name, vici_find_str(res, "", "errmsg"));
+		ret = FALSE;
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+static int load_conns(vici_conn_t *conn)
+{
+	u_int found = 0, loaded = 0, unloaded = 0;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg, *section;
+	enumerator_t *enumerator;
+	linked_list_t *conns;
+	settings_t *cfg;
+
+	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 --load-conns option");
+		}
+		break;
+	}
+
+	cfg = settings_create(SWANCTL_CONF);
+	if (!cfg)
+	{
+		fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF);
+		return EINVAL;
+	}
+
+	conns = list_conns(conn, format);
+
+	enumerator = cfg->create_section_enumerator(cfg, "connections");
+	while (enumerator->enumerate(enumerator, &section))
+	{
+		remove_from_list(conns, section);
+		found++;
+		if (load_conn(conn, cfg, section, format))
+		{
+			loaded++;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	cfg->destroy(cfg);
+
+	/* unload all connection in daemon, but not in file */
+	while (conns->remove_first(conns, (void**)&section) == SUCCESS)
+	{
+		if (unload_conn(conn, section, format))
+		{
+			unloaded++;
+		}
+		free(section);
+	}
+	conns->destroy(conns);
+
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		return 0;
+	}
+	if (found == 0)
+	{
+		printf("no connections found, %u unloaded\n", unloaded);
+		return 0;
+	}
+	if (loaded == found)
+	{
+		printf("successfully loaded %u connections, %u unloaded\n",
+			   loaded, unloaded);
+		return 0;
+	}
+	fprintf(stderr, "loaded %u of %u connections, %u failed to load, "
+			"%u unloaded\n", loaded, found, found - loaded, unloaded);
+	return EINVAL;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		load_conns, 'c', "load-conns", "(re-)load connection configuration",
+		{"[--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/load_creds.c b/src/swanctl/commands/load_creds.c
new file mode 100644
index 0000000..f77084c
--- /dev/null
+++ b/src/swanctl/commands/load_creds.c
@@ -0,0 +1,574 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "command.h"
+#include "swanctl.h"
+
+#include <credentials/sets/mem_cred.h>
+#include <credentials/sets/callback_cred.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)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool ret = TRUE;
+
+	req = vici_begin("load-cert");
+
+	vici_add_key_valuef(req, "type", "%s", type);
+	vici_add_key_value(req, "data", data.ptr, data.len);
+
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "load-cert request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "load-cert reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+	{
+		fprintf(stderr, "loading '%s' failed: %s\n",
+				dir, vici_find_str(res, "", "errmsg"));
+		ret = FALSE;
+	}
+	else
+	{
+		printf("loaded %s certificate '%s'\n", type, dir);
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+/**
+ * Load certficiates from a directory
+ */
+static void load_certs(vici_conn_t *conn, command_format_options_t format,
+					   char *type, char *dir)
+{
+	enumerator_t *enumerator;
+	struct stat st;
+	chunk_t *map;
+	char *path;
+
+	enumerator = enumerator_create_directory(dir);
+	if (enumerator)
+	{
+		while (enumerator->enumerate(enumerator, NULL, &path, &st))
+		{
+			if (S_ISREG(st.st_mode))
+			{
+				map = chunk_map(path, FALSE);
+				if (map)
+				{
+					load_cert(conn, format, path, type, *map);
+					chunk_unmap(map);
+				}
+				else
+				{
+					fprintf(stderr, "mapping '%s' failed: %s, skipped\n",
+							path, strerror(errno));
+				}
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+}
+
+/**
+ * Load a single private key over vici
+ */
+static bool load_key(vici_conn_t *conn, command_format_options_t format,
+					 char *dir, char *type, chunk_t data)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool ret = TRUE;
+
+	req = vici_begin("load-key");
+
+	vici_add_key_valuef(req, "type", "%s", type);
+	vici_add_key_value(req, "data", data.ptr, data.len);
+
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "load-key request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "load-key reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+	{
+		fprintf(stderr, "loading '%s' failed: %s\n",
+				dir, vici_find_str(res, "", "errmsg"));
+		ret = FALSE;
+	}
+	else
+	{
+		printf("loaded %s key '%s'\n", type, dir);
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+/**
+ * Callback function to prompt for private key passwords
+ */
+CALLBACK(password_cb, shared_key_t*,
+	char *prompt, shared_key_type_t type,
+	identification_t *me, identification_t *other,
+	id_match_t *match_me, id_match_t *match_other)
+{
+	char *pwd = NULL;
+
+	if (type != SHARED_PRIVATE_KEY_PASS)
+	{
+		return NULL;
+	}
+#ifdef HAVE_GETPASS
+	pwd = getpass(prompt);
+#endif
+	if (!pwd || strlen(pwd) == 0)
+	{
+		return NULL;
+	}
+	if (match_me)
+	{
+		*match_me = ID_MATCH_PERFECT;
+	}
+	if (match_other)
+	{
+		*match_other = ID_MATCH_PERFECT;
+	}
+	return shared_key_create(type, chunk_clone(chunk_from_str(pwd)));
+}
+
+/**
+ * Try to parse a potentially encrypted private key using password prompt
+ */
+static private_key_t* decrypt_key(char *name, char *type, chunk_t encoding)
+{
+	key_type_t kt = KEY_ANY;
+	private_key_t *private;
+	callback_cred_t *cb;
+	char buf[128];
+
+	if (streq(type, "rsa"))
+	{
+		kt = KEY_RSA;
+	}
+	else if (streq(type, "ecdsa"))
+	{
+		kt = KEY_ECDSA;
+	}
+
+	snprintf(buf, sizeof(buf), "Password for '%s': ", name);
+
+	cb = callback_cred_create_shared(password_cb, buf);
+	lib->credmgr->add_set(lib->credmgr, &cb->set);
+
+	private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, kt,
+								 BUILD_BLOB_PEM, encoding, BUILD_END);
+
+	lib->credmgr->remove_set(lib->credmgr, &cb->set);
+	cb->destroy(cb);
+
+	return private;
+}
+
+/**
+ * Try to parse a potentially encrypted private key using configured secret
+ */
+static private_key_t* decrypt_key_with_config(settings_t *cfg, char *name,
+											  char *type, chunk_t encoding)
+{	key_type_t kt = KEY_ANY;
+	enumerator_t *enumerator, *secrets;
+	char *section, *key, *value, *file, buf[128];
+	shared_key_t *shared;
+	private_key_t *private = NULL;
+	mem_cred_t *mem = NULL;
+
+	if (streq(type, "rsa"))
+	{
+		kt = KEY_RSA;
+	}
+	else if (streq(type, "ecdsa"))
+	{
+		kt = KEY_ECDSA;
+	}
+	else
+	{
+		type = "pkcs8";
+	}
+
+	/* load all secrets for this key type */
+	enumerator = cfg->create_section_enumerator(cfg, "secrets");
+	while (enumerator->enumerate(enumerator, &section))
+	{
+		if (strpfx(section, type))
+		{
+			file = cfg->get_str(cfg, "secrets.%s.file", NULL, section);
+			if (file && strcaseeq(file, name))
+			{
+				snprintf(buf, sizeof(buf), "secrets.%s", section);
+				secrets = cfg->create_key_value_enumerator(cfg, buf);
+				while (secrets->enumerate(secrets, &key, &value))
+				{
+					if (strpfx(key, "secret"))
+					{
+						if (!mem)
+						{
+							mem = mem_cred_create();
+						}
+						shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
+											chunk_clone(chunk_from_str(value)));
+						mem->add_shared(mem, shared, NULL);
+					}
+				}
+				secrets->destroy(secrets);
+			}
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	if (mem)
+	{
+		lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
+
+		private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, kt,
+									 BUILD_BLOB_PEM, encoding, BUILD_END);
+
+		lib->credmgr->remove_local_set(lib->credmgr, &mem->set);
+
+		if (!private)
+		{
+			fprintf(stderr, "configured decryption secret for '%s' invalid\n",
+					name);
+		}
+
+		mem->destroy(mem);
+	}
+
+	return private;
+}
+
+/**
+ * Try to decrypt and load a private key
+ */
+static bool load_encrypted_key(vici_conn_t *conn,
+							   command_format_options_t format, settings_t *cfg,
+							   char *rel, char *path, char *type, bool noprompt,
+							   chunk_t data)
+{
+	private_key_t *private;
+	bool loaded = FALSE;
+	chunk_t encoding;
+
+	private = decrypt_key_with_config(cfg, rel, type, data);
+	if (!private && !noprompt)
+	{
+		private = decrypt_key(rel, type, data);
+	}
+	if (private)
+	{
+		if (private->get_encoding(private, PRIVKEY_ASN1_DER, &encoding))
+		{
+			switch (private->get_type(private))
+			{
+				case KEY_RSA:
+					loaded = load_key(conn, format, path, "rsa", encoding);
+					break;
+				case KEY_ECDSA:
+					loaded = load_key(conn, format, path, "ecdsa", encoding);
+					break;
+				default:
+					break;
+			}
+			chunk_clear(&encoding);
+		}
+		private->destroy(private);
+	}
+	return loaded;
+}
+
+/**
+ * Load private keys from a directory
+ */
+static void load_keys(vici_conn_t *conn, command_format_options_t format,
+					  bool noprompt, settings_t *cfg, char *type, char *dir)
+{
+	enumerator_t *enumerator;
+	struct stat st;
+	chunk_t *map;
+	char *path, *rel;
+
+	enumerator = enumerator_create_directory(dir);
+	if (enumerator)
+	{
+		while (enumerator->enumerate(enumerator, &rel, &path, &st))
+		{
+			if (S_ISREG(st.st_mode))
+			{
+				map = chunk_map(path, FALSE);
+				if (map)
+				{
+					if (!load_encrypted_key(conn, format, cfg, rel, path, type,
+											noprompt, *map))
+					{
+						load_key(conn, format, path, type, *map);
+					}
+					chunk_unmap(map);
+				}
+				else
+				{
+					fprintf(stderr, "mapping '%s' failed: %s, skipped\n",
+							path, strerror(errno));
+				}
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+}
+
+/**
+ * Load a single secret over VICI
+ */
+static bool load_secret(vici_conn_t *conn, settings_t *cfg,
+						char *section, command_format_options_t format)
+{
+	enumerator_t *enumerator;
+	vici_req_t *req;
+	vici_res_t *res;
+	chunk_t data;
+	char *key, *value, buf[128], *type = NULL;
+	bool ret = TRUE;
+	int i;
+	char *types[] = {
+		"eap",
+		"xauth",
+		"ike",
+		"rsa",
+		"ecdsa",
+		"pkcs8",
+	};
+
+	for (i = 0; i < countof(types); i++)
+	{
+		if (strpfx(section, types[i]))
+		{
+			type = types[i];
+			break;
+		}
+	}
+	if (!type)
+	{
+		fprintf(stderr, "ignoring unsupported secret '%s'\n", section);
+		return FALSE;
+	}
+	if (!streq(type, "eap") && !streq(type, "xauth") && !streq(type, "ike"))
+	{	/* skip non-shared secrets */
+		return TRUE;
+	}
+
+	value = cfg->get_str(cfg, "secrets.%s.secret", NULL, section);
+	if (!value)
+	{
+		fprintf(stderr, "missing secret in '%s', ignored\n", section);
+		return FALSE;
+	}
+	if (strcasepfx(value, "0x"))
+	{
+		data = chunk_from_hex(chunk_from_str(value + 2), NULL);
+	}
+	else if (strcasepfx(value, "0s"))
+	{
+		data = chunk_from_base64(chunk_from_str(value + 2), NULL);
+	}
+	else
+	{
+		data = chunk_clone(chunk_from_str(value));
+	}
+
+	req = vici_begin("load-shared");
+
+	vici_add_key_valuef(req, "type", "%s", type);
+	vici_add_key_value(req, "data", data.ptr, data.len);
+	chunk_clear(&data);
+
+	vici_begin_list(req, "owners");
+	snprintf(buf, sizeof(buf), "secrets.%s", section);
+	enumerator = cfg->create_key_value_enumerator(cfg, buf);
+	while (enumerator->enumerate(enumerator, &key, &value))
+	{
+		if (strpfx(key, "id"))
+		{
+			vici_add_list_itemf(req, "%s", value);
+		}
+	}
+	enumerator->destroy(enumerator);
+	vici_end_list(req);
+
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "load-shared request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "load-shared reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+	{
+		fprintf(stderr, "loading shared secret failed: %s\n",
+				vici_find_str(res, "", "errmsg"));
+		ret = FALSE;
+	}
+	else
+	{
+		printf("loaded %s secret '%s'\n", type, section);
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+/**
+ * Clear all currently loaded credentials
+ */
+static bool clear_creds(vici_conn_t *conn, command_format_options_t format)
+{
+	vici_res_t *res;
+
+	res = vici_submit(vici_begin("clear-creds"), conn);
+	if (!res)
+	{
+		fprintf(stderr, "clear-creds request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "clear-creds reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	vici_free_res(res);
+	return TRUE;
+}
+
+static int load_creds(vici_conn_t *conn)
+{
+	bool clear = FALSE, noprompt = FALSE;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	enumerator_t *enumerator;
+	settings_t *cfg;
+	char *arg, *section;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 'c':
+				clear = TRUE;
+				continue;
+			case 'n':
+				noprompt = TRUE;
+				continue;
+			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 --load-creds option");
+		}
+		break;
+	}
+
+	if (clear)
+	{
+		if (!clear_creds(conn, format))
+		{
+			return ECONNREFUSED;
+		}
+	}
+
+	cfg = settings_create(SWANCTL_CONF);
+	if (!cfg)
+	{
+		fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF);
+		return EINVAL;
+	}
+
+	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_keys(conn, format, noprompt, cfg, "rsa", SWANCTL_RSADIR);
+	load_keys(conn, format, noprompt, cfg, "ecdsa", SWANCTL_ECDSADIR);
+	load_keys(conn, format, noprompt, cfg, "any", SWANCTL_PKCS8DIR);
+
+	enumerator = cfg->create_section_enumerator(cfg, "secrets");
+	while (enumerator->enumerate(enumerator, &section))
+	{
+		load_secret(conn, cfg, section, format);
+	}
+	enumerator->destroy(enumerator);
+
+	cfg->destroy(cfg);
+
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		load_creds, 's', "load-creds", "(re-)load credentials",
+		{"[--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"clear",		'c', 0, "clear previously loaded credentials"},
+			{"noprompt",	'n', 0, "do not prompt for passwords"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/load_pools.c b/src/swanctl/commands/load_pools.c
new file mode 100644
index 0000000..0ec56cc
--- /dev/null
+++ b/src/swanctl/commands/load_pools.c
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "command.h"
+#include "swanctl.h"
+
+/**
+ * Add a vici list from a comma separated string value
+ */
+static void add_list_key(vici_req_t *req, char *key, char *value)
+{
+	enumerator_t *enumerator;
+	char *token;
+
+	vici_begin_list(req, key);
+	enumerator = enumerator_create_token(value, ",", " ");
+	while (enumerator->enumerate(enumerator, &token))
+	{
+		vici_add_list_itemf(req, "%s", token);
+	}
+	enumerator->destroy(enumerator);
+	vici_end_list(req);
+}
+
+/**
+ * Translate setting key/values from a section into vici key-values/lists
+ */
+static void add_key_values(vici_req_t *req, settings_t *cfg, char *section)
+{
+	enumerator_t *enumerator;
+	char *key, *value;
+
+	enumerator = cfg->create_key_value_enumerator(cfg, section);
+	while (enumerator->enumerate(enumerator, &key, &value))
+	{
+		/* pool subnet is encoded as key/value, all other attributes as list */
+		if (streq(key, "addrs"))
+		{
+			vici_add_key_valuef(req, key, "%s", value);
+		}
+		else
+		{
+			add_list_key(req, key, value);
+		}
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Load a pool configuration
+ */
+static bool load_pool(vici_conn_t *conn, settings_t *cfg,
+					  char *section, command_format_options_t format)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool ret = TRUE;
+	char buf[128];
+
+	snprintf(buf, sizeof(buf), "%s.%s", "pools", section);
+
+	req = vici_begin("load-pool");
+
+	vici_begin_section(req, section);
+	add_key_values(req, cfg, buf);
+	vici_end_section(req);
+
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "load-pool request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "load-pool reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+	{
+		fprintf(stderr, "loading pool '%s' failed: %s\n",
+				section, vici_find_str(res, "", "errmsg"));
+		ret = FALSE;
+	}
+	else
+	{
+		printf("loaded pool '%s'\n", section);
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+CALLBACK(list_pool, int,
+	linked_list_t *list, vici_res_t *res, char *name)
+{
+	list->insert_last(list, strdup(name));
+	return 0;
+}
+
+/**
+ * Create a list of currently loaded pools
+ */
+static linked_list_t* list_pools(vici_conn_t *conn,
+								 command_format_options_t format)
+{
+	linked_list_t *list;
+	vici_res_t *res;
+
+	list = linked_list_create();
+
+	res = vici_submit(vici_begin("get-pools"), conn);
+	if (res)
+	{
+		if (format & COMMAND_FORMAT_RAW)
+		{
+			vici_dump(res, "get-pools reply", format & COMMAND_FORMAT_PRETTY,
+					  stdout);
+		}
+		vici_parse_cb(res, list_pool, NULL, NULL, list);
+		vici_free_res(res);
+	}
+	return list;
+}
+
+/**
+ * Remove and free a string from a list
+ */
+static void remove_from_list(linked_list_t *list, char *str)
+{
+	enumerator_t *enumerator;
+	char *current;
+
+	enumerator = list->create_enumerator(list);
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (streq(current, str))
+		{
+			list->remove_at(list, enumerator);
+			free(current);
+		}
+	}
+	enumerator->destroy(enumerator);
+}
+
+/**
+ * Unload a pool by name
+ */
+static bool unload_pool(vici_conn_t *conn, char *name,
+						command_format_options_t format)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	bool ret = TRUE;
+
+	req = vici_begin("unload-pool");
+	vici_add_key_valuef(req, "name", "%s", name);
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "unload-pool request failed: %s\n", strerror(errno));
+		return FALSE;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "unload-pool reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+	{
+		fprintf(stderr, "unloading pool '%s' failed: %s\n",
+				name, vici_find_str(res, "", "errmsg"));
+		ret = FALSE;
+	}
+	vici_free_res(res);
+	return ret;
+}
+
+static int load_pools(vici_conn_t *conn)
+{
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	u_int found = 0, loaded = 0, unloaded = 0;
+	char *arg, *section;
+	enumerator_t *enumerator;
+	linked_list_t *pools;
+	settings_t *cfg;
+
+	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 --load-pools option");
+		}
+		break;
+	}
+
+	cfg = settings_create(SWANCTL_CONF);
+	if (!cfg)
+	{
+		fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF);
+		return EINVAL;
+	}
+
+	pools = list_pools(conn, format);
+
+	enumerator = cfg->create_section_enumerator(cfg, "pools");
+	while (enumerator->enumerate(enumerator, &section))
+	{
+		remove_from_list(pools, section);
+		found++;
+		if (load_pool(conn, cfg, section, format))
+		{
+			loaded++;
+		}
+	}
+	enumerator->destroy(enumerator);
+
+	cfg->destroy(cfg);
+
+	/* unload all pools in daemon, but not in file */
+	while (pools->remove_first(pools, (void**)&section) == SUCCESS)
+	{
+		if (unload_pool(conn, section, format))
+		{
+			unloaded++;
+		}
+		free(section);
+	}
+	pools->destroy(pools);
+
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		return 0;
+	}
+	if (found == 0)
+	{
+		printf("no pools found, %u unloaded\n", unloaded);
+		return 0;
+	}
+	if (loaded == found)
+	{
+		printf("successfully loaded %u pools, %u unloaded\n",
+			   loaded, unloaded);
+		return 0;
+	}
+	fprintf(stderr, "loaded %u of %u pools, %u failed to load, "
+			"%u unloaded\n", loaded, found, found - loaded, unloaded);
+	return EINVAL;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		load_pools, 'a', "load-pools", "(re-)load pool configuration",
+		{"[--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/log.c b/src/swanctl/commands/log.c
new file mode 100644
index 0000000..99ba328
--- /dev/null
+++ b/src/swanctl/commands/log.c
@@ -0,0 +1,101 @@
+/*
+ * 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 "command.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+CALLBACK(log_cb, void,
+	command_format_options_t *format, char *name, vici_res_t *msg)
+{
+	if (*format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(msg, "log", *format & COMMAND_FORMAT_PRETTY, stdout);
+	}
+	else
+	{
+		char *current, *next;
+
+		current = vici_find_str(msg, NULL, "msg");
+		while (current)
+		{
+			next = strchr(current, '\n');
+			printf("%.2d[%s] ", vici_find_int(msg, 0, "thread"),
+				   vici_find_str(msg, "   ", "group"));
+			if (next == NULL)
+			{
+				printf("%s\n", current);
+				break;
+			}
+			printf("%.*s\n", (int)(next - current), current);
+			current = next + 1;
+		}
+	}
+}
+
+static int logcmd(vici_conn_t *conn)
+{
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg;
+
+	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 --log option");
+		}
+		break;
+	}
+
+	if (vici_register(conn, "log", log_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for log failed: %s\n", strerror(errno));
+		return errno;
+	}
+
+	wait_sigint();
+
+	fprintf(stderr, "disconnecting...\n");
+
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		logcmd, 'T', "log", "trace logging output",
+		{"[--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/stats.c b/src/swanctl/commands/stats.c
new file mode 100644
index 0000000..b5425f5
--- /dev/null
+++ b/src/swanctl/commands/stats.c
@@ -0,0 +1,118 @@
+/*
+ * 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 "command.h"
+
+#include <errno.h>
+
+static int stats(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	char *arg;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+
+	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 --stats option");
+		}
+		break;
+	}
+
+	req = vici_begin("stats");
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "stats request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "stats reply", format & COMMAND_FORMAT_PRETTY, stdout);
+	}
+	else
+	{
+		printf("uptime: %s, since %s\n",
+			vici_find_str(res, "", "uptime.running"),
+			vici_find_str(res, "", "uptime.since"));
+
+		printf("worker threads: %s total, %s idle, working: %s/%s/%s/%s\n",
+			vici_find_str(res, "", "workers.total"),
+			vici_find_str(res, "", "workers.idle"),
+			vici_find_str(res, "", "workers.active.critical"),
+			vici_find_str(res, "", "workers.active.high"),
+			vici_find_str(res, "", "workers.active.medium"),
+			vici_find_str(res, "", "workers.active.low"));
+
+		printf("job queues: %s/%s/%s/%s\n",
+			vici_find_str(res, "", "queues.critical"),
+			vici_find_str(res, "", "queues.high"),
+			vici_find_str(res, "", "queues.medium"),
+			vici_find_str(res, "", "queues.low"));
+
+		printf("jobs scheduled: %s\n",
+			vici_find_str(res, "", "scheduled"));
+
+		printf("IKE_SAs: %s total, %s half-open\n",
+			vici_find_str(res, "", "ikesas.total"),
+			vici_find_str(res, "", "ikesas.half-open"));
+
+		if (vici_find_str(res, NULL, "mem.total"))
+		{
+			printf("memory usage: %s bytes, %s allocations\n",
+				vici_find_str(res, "", "mem.total"),
+				vici_find_str(res, "", "mem.allocs"));
+		}
+		if (vici_find_str(res, NULL, "mallinfo.sbrk"))
+		{
+			printf("mallinfo: sbrk %s, mmap %s, used %s, free %s\n",
+				vici_find_str(res, "", "mallinfo.sbrk"),
+				vici_find_str(res, "", "mallinfo.mmap"),
+				vici_find_str(res, "", "mallinfo.used"),
+				vici_find_str(res, "", "mallinfo.free"));
+		}
+	}
+	vici_free_res(res);
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		stats, 'S', "stats", "show daemon stats information",
+		{"[--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/terminate.c b/src/swanctl/commands/terminate.c
new file mode 100644
index 0000000..689ba4d
--- /dev/null
+++ b/src/swanctl/commands/terminate.c
@@ -0,0 +1,157 @@
+/*
+ * 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 "command.h"
+
+#include <errno.h>
+
+CALLBACK(log_cb, void,
+	command_format_options_t *format, char *name, vici_res_t *msg)
+{
+	if (*format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(msg, "log", *format & COMMAND_FORMAT_PRETTY, stdout);
+	}
+	else
+	{
+		printf("[%s] %s\n",
+			   vici_find_str(msg, "   ", "group"),
+			   vici_find_str(msg, "", "msg"));
+	}
+}
+
+static int terminate(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg, *child = NULL, *ike = NULL;
+	int ret = 0, timeout = 0, level = 1, child_id = 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 'c':
+				child = arg;
+				continue;
+			case 'i':
+				ike = arg;
+				continue;
+			case 'C':
+				child_id = atoi(arg);
+				continue;
+			case 'I':
+				ike_id = atoi(arg);
+				continue;
+			case 't':
+				timeout = atoi(arg);
+				continue;
+			case 'l':
+				level = atoi(arg);
+				continue;
+			case EOF:
+				break;
+			default:
+				return command_usage("invalid --terminate option");
+		}
+		break;
+	}
+
+	if (vici_register(conn, "control-log", log_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for log failed: %s\n", strerror(errno));
+		return errno;
+	}
+	req = vici_begin("terminate");
+	if (child)
+	{
+		vici_add_key_valuef(req, "child", "%s", child);
+	}
+	if (ike)
+	{
+		vici_add_key_valuef(req, "ike", "%s", ike);
+	}
+	if (child_id)
+	{
+		vici_add_key_valuef(req, "child-id", "%d", child_id);
+	}
+	if (ike_id)
+	{
+		vici_add_key_valuef(req, "ike-id", "%d", ike_id);
+	}
+	if (timeout)
+	{
+		vici_add_key_valuef(req, "timeout", "%d", timeout * 1000);
+	}
+	vici_add_key_valuef(req, "loglevel", "%d", level);
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "terminate request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "terminate reply", format & COMMAND_FORMAT_PRETTY,
+				  stdout);
+	}
+	else
+	{
+		if (streq(vici_find_str(res, "no", "success"), "yes"))
+		{
+			printf("terminate completed successfully\n");
+		}
+		else
+		{
+			fprintf(stderr, "terminate 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) {
+		terminate, 't', "terminate", "terminate a connection",
+		{"--child <name> | --ike <name | --child-id <id> | --ike-id <id>",
+		 "[--timeout <s>] [--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"child",		'c', 1, "terminate by CHILD_SA name"},
+			{"ike",			'i', 1, "terminate by IKE_SA name"},
+			{"child-id",	'C', 1, "terminate by CHILD_SA reqid"},
+			{"ike-id",		'I', 1, "terminate by IKE_SA unique identifier"},
+			{"timeout",		't', 1, "timeout in seconds before detaching"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+			{"loglevel",	'l', 1, "verbosity of redirected log"},
+		}
+	});
+}
diff --git a/src/swanctl/commands/version.c b/src/swanctl/commands/version.c
new file mode 100644
index 0000000..4f24a0f
--- /dev/null
+++ b/src/swanctl/commands/version.c
@@ -0,0 +1,96 @@
+/*
+ * 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 "command.h"
+
+#include <errno.h>
+
+static int version(vici_conn_t *conn)
+{
+	vici_req_t *req;
+	vici_res_t *res;
+	char *arg;
+	bool daemon = FALSE;
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+
+	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 'd':
+				daemon = TRUE;
+				continue;
+			case EOF:
+				break;
+			default:
+				return command_usage("invalid --terminate option");
+		}
+		break;
+	}
+
+	if (!daemon)
+	{
+		printf("strongSwan swanctl %s\n", VERSION);
+		return 0;
+	}
+
+	req = vici_begin("version");
+	res = vici_submit(req, conn);
+	if (!res)
+	{
+		fprintf(stderr, "version request failed: %s\n", strerror(errno));
+		return errno;
+	}
+	if (format & COMMAND_FORMAT_RAW)
+	{
+		vici_dump(res, "version reply", format & COMMAND_FORMAT_PRETTY, stdout);
+	}
+	else
+	{
+		printf("strongSwan %s %s (%s, %s, %s)\n",
+			vici_find_str(res, "", "version"),
+			vici_find_str(res, "", "daemon"),
+			vici_find_str(res, "", "sysname"),
+			vici_find_str(res, "", "release"),
+			vici_find_str(res, "", "machine"));
+	}
+	vici_free_res(res);
+	return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+	command_register((command_t) {
+		version, 'v', "version", "show version information",
+		{"[--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"daemon",		'd', 0, "query daemon version"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
diff --git a/src/swanctl/swanctl.8.in b/src/swanctl/swanctl.8.in
new file mode 100644
index 0000000..d7abae6
--- /dev/null
+++ b/src/swanctl/swanctl.8.in
@@ -0,0 +1,83 @@
+.TH SWANCTL 8 "2014-04-28" "@PACKAGE_VERSION@" "strongSwan"
+.SH NAME
+swanctl \- strongSwan configuration, control and monitoring command line interface.
+.SH SYNOPSIS
+.SY "swanctl"
+.I command
+.RI [ option\~ .\|.\|.]
+.YS
+.
+.SY "swanctl"
+.B \-h
+|
+.B \-\-help
+.YS
+.
+.SH DESCRIPTION
+swanctl is a cross-platform command line utility to configure, control and
+monitor the strongSwan IKE daemon. It is a replacement for the aging
+.BR starter ,
+.B ipsec
+and
+.B stroke
+tools.
+
+swanctl uses a configuration file called
+.BR swanctl.conf (5)
+to parse configurations and credentials. Private keys, certificates and other
+PKI related credentials are read from specific directories.
+
+To communicate with the IKE daemon, swanctl uses the VICI protocol, the
+Versatile IKE Configuration Interface. This stable interface is usable by
+other tools and is often preferable than scripting swanctl and parsing its
+output.
+
+.SH COMMANDS
+.TP
+.B "\-i, \-\-initiate"
+initiate a connection
+.TP
+.B "\-t, \-\-terminate"
+\-\-terminate\fR
+terminate a connection
+.TP
+.B "\-p, \-\-install"
+install a trap or shunt policy
+.TP
+.B "\-u, \-\-uninstall"
+uninstall a trap or shunt policy
+.TP
+.B "\-l, \-\-list\-sas"
+list currently active IKE_SAs
+.TP
+.B "\-P, \-\-list\-pols"
+list currently installed policies
+.TP
+.B "\-L, \-\-list\-conns"
+list loaded configurations
+.TP
+.B "\-x, \-\-list\-certs"
+list stored certificates
+.TP
+.B "\-A, \-\-list\-pools"
+list loaded pool configurations
+.TP
+.B "\-c, \-\-load\-conns"
+(re\-)load connection configuration
+.TP
+.B "\-s, \-\-load\-creds"
+(re\-)load credentials
+.TP
+.B "\-a, \-\-load\-pools"
+(re\-)load pool configuration
+.TP
+.B "\-T, \-\-log"
+trace logging output
+.TP
+.B "\-v, \-\-version"
+show daemon version information
+.TP
+.B "\-h, \-\-help"
+show usage information
+.SH SEE ALSO
+.BR swanctl.conf (5)
diff --git a/src/swanctl/swanctl.c b/src/swanctl/swanctl.c
new file mode 100644
index 0000000..dc5af79
--- /dev/null
+++ b/src/swanctl/swanctl.c
@@ -0,0 +1,57 @@
+/*
+ * 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 "command.h"
+
+#include <unistd.h>
+
+#include <library.h>
+
+/**
+ * Cleanup library atexit()
+ */
+static void cleanup()
+{
+	lib->processor->cancel(lib->processor);
+	library_deinit();
+}
+
+/**
+ * Library initialization and operation parsing
+ */
+int main(int argc, char *argv[])
+{
+	atexit(cleanup);
+	if (!library_init(NULL, "swanctl"))
+	{
+		exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
+	}
+	if (lib->integrity &&
+		!lib->integrity->check_file(lib->integrity, "swanctl", argv[0]))
+	{
+		fprintf(stderr, "integrity check of swanctl failed\n");
+		exit(SS_RC_DAEMON_INTEGRITY);
+	}
+	if (!lib->plugins->load(lib->plugins,
+			lib->settings->get_str(lib->settings, "swanctl.load", PLUGINS)))
+	{
+		exit(SS_RC_INITIALIZATION_FAILED);
+	}
+	dbg_default_set_level(0);
+	lib->processor->set_threads(lib->processor, 4);
+	dbg_default_set_level(1);
+
+	return command_dispatch(argc, argv);
+}
diff --git a/src/swanctl/swanctl.conf b/src/swanctl/swanctl.conf
new file mode 100644
index 0000000..8cff81f
--- /dev/null
+++ b/src/swanctl/swanctl.conf
@@ -0,0 +1,306 @@
+# Section defining IKE connection configurations.
+# connections {
+
+    # Section for an IKE connection named <conn>.
+    # <conn> {
+
+        # IKE major version to use for connection.
+        # version = 0
+
+        # Local address(es) to use for IKE communication, comma separated.
+        # local_addrs = %any
+
+        # Remote address(es) to use for IKE communication, comma separated.
+        # remote_addrs = %any
+
+        # Local UPD port for IKE communication.
+        # local_port = 500
+
+        # Remote UDP port for IKE communication.
+        # remote_port = 500
+
+        # Comma separated proposals to accept for IKE.
+        # proposals = default
+
+        # Virtual IPs to request in configuration payload / Mode Config.
+        # vips =
+
+        # Use Aggressive Mode in IKEv1.
+        # aggressive = no
+
+        # Set the Mode Config mode to use.
+        # pull = yes
+
+        # Enforce UDP encapsulation by faking NAT-D payloads.
+        # encap = no
+
+        # Enables MOBIKE on IKEv2 connections.
+        # mobike = yes
+
+        # Interval of liveness checks (DPD).
+        # dpd_delay = 0s
+
+        # Timeout for DPD checks (IKEV1 only).
+        # dpd_timeout = 0s
+
+        # Use IKEv1 UDP packet fragmentation (yes, no or force).
+        # fragmentation = no
+
+        # Send certificate requests payloads (yes or no).
+        # send_certreq = yes
+
+        # Send certificate payloads (yes, no or ifasked).
+        # send_cert = ifasked
+
+        # Number of retransmission sequences to perform during initial connect.
+        # keyingtries = 1
+
+        # Connection uniqueness policy (never, no, keep or replace).
+        # unique = no
+
+        # Time to schedule IKE reauthentication.
+        # reauth_time = 0s
+
+        # Time to schedule IKE rekeying.
+        # rekey_time = 4h
+
+        # Hard IKE_SA lifetime if rekey/reauth does not complete, as time.
+        # over_time = 10% of rekey_time/reauth_time
+
+        # Range of random time to subtract from rekey/reauth times.
+        # rand_time = over_time
+
+        # Comma separated list of named IP pools.
+        # pools =
+
+        # Section for a local authentication round.
+        # local<suffix> {
+
+            # Comma separated list of certificate candidates to use for
+            # authentication.
+            # certs =
+
+            # Authentication to perform locally (pubkey, psk, xauth[-backend] or
+            # eap[-method]).
+            # auth = pubkey
+
+            # IKE identity to use for authentication round.
+            # id =
+
+            # Client EAP-Identity to use in EAP-Identity exchange and the EAP
+            # method.
+            # eap_id = id
+
+            # Server side EAP-Identity to expect in the EAP method.
+            # aaa_id = remote-id
+
+            # Client XAuth username used in the XAuth exchange.
+            # xauth_id = id
+
+        # }
+
+        # Section for a remote authentication round.
+        # remote<suffix> {
+
+            # IKE identity to expect for authentication round.
+            # id = %any
+
+            # Authorization group memberships to require.
+            # groups =
+
+            # Comma separated list of certificate to accept for authentication.
+            # certs =
+
+            # Comma separated list of CA certificates to accept for
+            # authentication.
+            # cacert =
+
+            # Certificate revocation policy, (strict, ifuri or relaxed).
+            # revocation = relaxed
+
+            # Authentication to expect from remote (pubkey, psk, xauth[-backend]
+            # or eap[-method]).
+            # auth = pubkey
+
+        # }
+
+        # children {
+
+            # CHILD_SA configuration sub-section.
+            # <child> {
+
+                # AH proposals to offer for the CHILD_SA.
+                # ah_proposals =
+
+                # ESP proposals to offer for the CHILD_SA.
+                # esp_proposals = default
+
+                # Local traffic selectors to include in CHILD_SA.
+                # local_ts = dynamic
+
+                # Remote selectors to include in CHILD_SA.
+                # remote_ts = dynamic
+
+                # Time to schedule CHILD_SA rekeying.
+                # rekey_time = 1h
+
+                # Maximum lifetime before CHILD_SA gets closed, as time.
+                # life_time = rekey_time + 10%
+
+                # Range of random time to subtract from rekey_time.
+                # rand_time = life_time - rekey_time
+
+                # Number of bytes processed before initiating CHILD_SA rekeying.
+                # rekey_bytes = 0
+
+                # Maximum bytes processed before CHILD_SA gets closed.
+                # life_bytes = rekey_bytes + 10%
+
+                # Range of random bytes to subtract from rekey_bytes.
+                # rand_bytes = life_bytes - rekey_bytes
+
+                # Number of packets processed before initiating CHILD_SA
+                # rekeying.
+                # rekey_packets = 0
+
+                # Maximum number of packets processed before CHILD_SA gets
+                # closed.
+                # life_packets = rekey_packets + 10%
+
+                # Range of random packets to subtract from packets_bytes.
+                # rand_packets = life_packets - rekey_packets
+
+                # Updown script to invoke on CHILD_SA up and down events.
+                # updown =
+
+                # Hostaccess variable to pass to updown script.
+                # hostaccess = yes
+
+                # IPsec Mode to establish (tunnel, transport, beet, pass or
+                # drop).
+                # mode = tunnel
+
+                # Action to perform on DPD timeout (clear, trap or restart).
+                # dpd_action = clear
+
+                # Enable IPComp compression before encryption.
+                # ipcomp = no
+
+                # Timeout before closing CHILD_SA after inactivity.
+                # inactivity = 0s
+
+                # Fixed reqid to use for this CHILD_SA.
+                # reqid = 0
+
+                # Netfilter mark and mask for input traffic.
+                # mark_in = 0/0x00000000
+
+                # Netfilter mark and mask for output traffic.
+                # mark_out = 0/0x00000000
+
+                # Traffic Flow Confidentiality padding.
+                # tfc_padding = 0
+
+                # IPsec replay window to configure for this CHILD_SA.
+                # replay_window = 32
+
+                # Action to perform after loading the configuration (none, trap,
+                # start).
+                # start_action = none
+
+                # Action to perform after a CHILD_SA gets closed (none, trap,
+                # start).
+                # close_action = none
+
+            # }
+
+        # }
+
+    # }
+
+# }
+
+# Section defining secrets for IKE/EAP/XAuth authentication and private key
+# decryption.
+# secrets {
+
+    # EAP secret section for a specific secret.
+    # eap<suffix> {
+
+        # Value of the EAP/XAuth secret.
+        # secret =
+
+        # Identity the EAP/XAuth secret belongs to.
+        # id<suffix> =
+
+    # }
+
+    # XAuth secret section for a specific secret.
+    # xauth<suffix> {
+
+    # }
+
+    # IKE preshared secret section for a specific secret.
+    # ike<suffix> {
+
+        # Value of the IKE preshared secret.
+        # secret =
+
+        # IKE identity the IKE preshared secret belongs to.
+        # id<suffix> =
+
+    # }
+
+    # Private key decryption passphrase for a key in the rsa folder.
+    # rsa<suffix> {
+
+        # File name in the rsa folder for which this passphrase should be used.
+        # file =
+
+        # Value of decryption passphrase for RSA key.
+        # secret =
+
+    # }
+
+    # Private key decryption passphrase for a key in the ecdsa folder.
+    # ecdsa<suffix> {
+
+        # File name in the ecdsa folder for which this passphrase should be
+        # used.
+        # file =
+
+        # Value of decryption passphrase for ECDSA key.
+        # secret =
+
+    # }
+
+    # Private key decryption passphrase for a key in the pkcs8 folder.
+    # pkcs8<suffix> {
+
+        # File name in the pkcs8 folder for which this passphrase should be
+        # used.
+        # file =
+
+        # Value of decryption passphrase for PKCS#8 key.
+        # secret =
+
+    # }
+
+# }
+
+# Section defining named pools.
+# pools {
+
+    # Section defining a single pool with a unique name.
+    # <name> {
+
+        # Subnet defining addresses allocated in pool.
+        # addrs =
+
+        # Comma separated list of additional attributes from type <attr>.
+        # <attr> =
+
+    # }
+
+# }
+
diff --git a/src/swanctl/swanctl.conf.5.head.in b/src/swanctl/swanctl.conf.5.head.in
new file mode 100644
index 0000000..84f734e
--- /dev/null
+++ b/src/swanctl/swanctl.conf.5.head.in
@@ -0,0 +1,24 @@
+.TH SWANCTL.CONF 5 "" "@PACKAGE_VERSION@" "strongSwan"
+.SH NAME
+swanctl.conf \- swanctl configuration file
+.SH DESCRIPTION
+swanctl.conf is the configuration file used by the
+.BR swanctl (8)
+tool to load configurations and credentials into the strongSwan IKE daemon.
+
+For a description of the basic file syntax refer to
+.BR strongswan.conf (5).
+
+.SH TIME FORMATS
+For all options that define a time, the time is specified in seconds. The
+.RI "" "s" ","
+.RI "" "m" ","
+.RI "" "h" ""
+and
+.RI "" "d" ""
+suffixes explicitly define the units for seconds, minutes, hours and days,
+respectively.
+
+.SH SETTINGS
+The following settings can be used to configure connections, credentials and
+pools.
diff --git a/src/swanctl/swanctl.conf.5.main b/src/swanctl/swanctl.conf.5.main
new file mode 100644
index 0000000..3d0b0e8
--- /dev/null
+++ b/src/swanctl/swanctl.conf.5.main
@@ -0,0 +1,957 @@
+.TP
+.B connections
+.br
+Section defining IKE connection configurations.
+
+The connections section defines IKE connection configurations, each in its own
+subsections. In the keyword description below, the connection is named
+.RI "" "<conn>" ","
+but an arbitrary yet unique connection name can be chosen for each connection
+subsection.
+
+.TP
+.B connections.<conn>
+.br
+Section for an IKE connection named <conn>.
+
+.TP
+.BR connections.<conn>.version " [0]"
+IKE major version to use for connection.
+.RI "" "1" ""
+uses IKEv1 aka ISAKMP,
+.RI "" "2" ""
+uses
+IKEv2. A connection using the default of
+.RI "" "0" ""
+accepts both IKEv1 and IKEv2 as
+responder, and initiates the connection actively with IKEv2.
+
+.TP
+.BR connections.<conn>.local_addrs " [%any]"
+Local address(es) to use for IKE communication, comma separated. Takes single
+IPv4/IPv6 addresses, DNS names, CIDR subnets or IP address ranges.
+
+As initiator, the first non\-range/non\-subnet is used to initiate the connection
+from. As responder, the local destination address must match at least to one of
+the specified addresses, subnets or ranges.
+
+.TP
+.BR connections.<conn>.remote_addrs " [%any]"
+Remote address(es) to use for IKE communication, comma separated. Takes single
+IPv4/IPv6 addresses, DNS names, CIDR subnets or IP address ranges.
+
+As initiator, the first non\-range/non\-subnet is used to initiate the connection
+to. As responder, the initiator source address must match at least to one of the
+specified addresses, subnets or ranges.
+
+To initiate a connection, at least one specific address or DNS name must be
+specified.
+
+.TP
+.BR connections.<conn>.local_port " [500]"
+Local UPD port for IKE communication. By default the port of the socket backend
+is used, which is usually
+.RI "" "500" "."
+If port
+.RI "" "500" ""
+is used, automatic IKE port
+floating to port 4500 is used to work around NAT issues.
+
+Using a non\-default local IKE port requires support from the socket backend in
+use (socket\-dynamic).
+
+.TP
+.BR connections.<conn>.remote_port " [500]"
+Remote UPD 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.
+
+.TP
+.BR connections.<conn>.proposals " [default]"
+A proposal is a set of algorithms. For non\-AEAD algorithms, this includes for
+IKE an encryption algorithm, an integrity algorithm, a pseudo random function
+and a Diffie\-Hellman group. For AEAD algorithms, instead of encryption and
+integrity algorithms, a combined algorithm is used.
+
+In IKEv2, multiple algorithms of the same kind can be specified in a single
+proposal, from which one gets selected. In IKEv1, only one algorithm per kind is
+allowed per proposal, more algorithms get implicitly stripped. Use multiple
+proposals to offer different algorithms combinations in IKEv1.
+
+Algorithm keywords get separated using dashes. Multiple proposals may be
+separated by commas. The special value
+.RI "" "default" ""
+forms a default proposal of
+supported algorithms considered safe, and is usually a good choice for
+interoperability.
+
+.TP
+.BR connections.<conn>.vips " []"
+Comma separated list of virtual IPs to request in IKEv2 configuration payloads
+or IKEv1 Mode Config. The wildcard addresses
+.RI "" "0.0.0.0" ""
+and
+.RI "" "::" ""
+request an
+arbitrary address, specific addresses may be defined. The responder may return a
+different address, though, or none at all.
+
+.TP
+.BR connections.<conn>.aggressive " [no]"
+Enables Aggressive Mode instead of Main Mode with Identity Protection.
+Aggressive Mode is considered less secure, because the ID and HASH payloads are
+exchanged unprotected. This allows a passive attacker to snoop peer identities,
+and even worse, start dictionary attacks on the Preshared Key.
+
+.TP
+.BR connections.<conn>.pull " [yes]"
+If the default of
+.RI "" "yes" ""
+is used, Mode Config works in pull mode, where the
+initiator actively requests a virtual IP. With
+.RI "" "no" ","
+push mode is used, where
+the responder pushes down a virtual IP to the initiating peer.
+
+Push mode is currently supported for IKEv1, but not in IKEv2. It is used by a
+few implementations only, pull mode is recommended.
+
+.TP
+.BR connections.<conn>.encap " [no]"
+To enforce UDP encapsulation of ESP packets, the IKE daemon can fake the NAT
+detection payloads. This makes the peer believe that NAT takes place on the
+path, forcing it to encapsulate ESP packets in UDP.
+
+Usually this is not required, but it can help to work around connectivity issues
+with too restrictive intermediary firewalls.
+
+.TP
+.BR connections.<conn>.mobike " [yes]"
+Enables MOBIKE on IKEv2 connections. MOBIKE is enabled by default on IKEv2
+connections, and allows mobility of clients and multi\-homing on servers by
+migrating active IPsec tunnels.
+
+Usually keeping MOBIKE enabled is unproblematic, as it is not used if the peer
+does not indicate support for it. However, due to the design of MOBIKE, IKEv2
+always floats to port 4500 starting from the second exchange. Some
+implementations don't like this behavior, hence it can be disabled.
+
+.TP
+.BR connections.<conn>.dpd_delay " [0s]"
+Interval to check the liveness of a peer actively using IKEv2 INFORMATIONAL
+exchanges or IKEv1 R_U_THERE messages. Active DPD checking is only enforced if
+no IKE or ESP/AH packet has been received for the configured DPD delay.
+
+.TP
+.BR connections.<conn>.dpd_timeout " [0s]"
+Charon by default uses the normal retransmission mechanism and timeouts to check
+the liveness of a peer, as all messages are used for liveness checking. For
+compatibility reasons, with IKEv1 a custom interval may be specified; this
+option has no effect on connections using IKE2.
+
+.TP
+.BR connections.<conn>.fragmentation " [no]"
+The default of
+.RI "" "no" ""
+disables IKEv1 fragmentation mechanism,
+.RI "" "yes" ""
+enables it if
+support has been indicated by the peer.
+.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.
+
+.TP
+.BR connections.<conn>.send_certreq " [yes]"
+Send certificate request payloads to offer trusted root CA certificates to the
+peer. Certificate requests help the peer to choose an appropriate
+certificate/private key for authentication and are enabled by default.
+
+Disabling certificate requests can be useful if too many trusted root CA
+certificates are installed, as each certificate request increases the size of
+the initial IKE packets.
+
+.TP
+.BR connections.<conn>.send_cert " [ifasked]"
+Send certificate payloads when using certificate authentication. With the
+default of
+.RI "" "ifasked" ""
+the daemon sends certificate payloads only if certificate
+requests have been received.
+.RI "" "no" ""
+disables sending of certificate payloads,
+.RI "" "yes" ""
+always sends certificate payloads whenever certificate authentication is
+used.
+
+.TP
+.BR connections.<conn>.keyingtries " [1]"
+Number of retransmission sequences to perform during initial connect. Instead of
+giving up initiation after the first retransmission sequence with the default
+value of
+.RI "" "1" ","
+additional sequences may be started according to the configured
+value. A value of
+.RI "" "0" ""
+initiates a new sequence until the connection establishes
+or fails with a permanent error.
+
+.TP
+.BR connections.<conn>.unique " [no]"
+Connection uniqueness policy to enforce. To avoid multiple connections from the
+same user, a uniqueness policy can be enforced. The value
+.RI "" "never" ""
+does never
+enforce such a policy, even if a peer included INITIAL_CONTACT notification
+messages, whereas
+.RI "" "no" ""
+replaces existing connections for the same identity if a
+new one has the INITIAL_CONTACT notify.
+.RI "" "keep" ""
+rejects new connection attempts
+if the same user already has an active connection,
+.RI "" "replace" ""
+deletes any
+existing connection if a new one for the same user gets established.
+
+To compare connections for uniqueness, the remote IKE identity is used. If EAP
+or XAuth authentication is involved, the EAP\-Identity or XAuth username is used
+to enforce the uniqueness policy instead.
+
+.TP
+.BR connections.<conn>.reauth_time " [0s]"
+Time to schedule IKE reauthentication. IKE reauthentication recreates the
+IKE/ISAKMP SA from scratch and re\-evaluates the credentials. In asymmetric
+configurations (with EAP or configuration payloads) it might not be possible to
+actively reauthenticate as responder. The IKEv2 reauthentication lifetime
+negotiation can instruct the client to perform reauthentication.
+
+Reauthentication is disabled by default. Enabling it usually may lead to small
+connection interruptions, as strongSwan uses a break\-before\-make policy with
+IKEv2 to avoid any conflicts with associated tunnel resources.
+
+.TP
+.BR connections.<conn>.rekey_time " [4h]"
+IKE rekeying refreshes key material using a Diffie\-Hellman exchange, but does
+not re\-check associated credentials. It is supported in IKEv2 only, IKEv1
+performs a reauthentication procedure instead.
+
+With the default value IKE rekeying is scheduled every 4 hours, minus the
+configured
+.RB "" "rand_time" "."
+
+
+.TP
+.BR connections.<conn>.over_time " [10% of rekey_time/reauth_time]"
+Hard IKE_SA lifetime if rekey/reauth does not complete, as time. To avoid having
+an IKE/ISAKMP kept alive if IKE reauthentication or rekeying fails perpetually,
+a maximum hard lifetime may be specified. If the IKE_SA fails to rekey or
+reauthenticate within the specified time, the IKE_SA gets closed.
+
+In contrast to CHILD_SA rekeying,
+.RB "" "over_time" ""
+is relative in time to the
+.RB "" "rekey_time" ""
+.RI "" "and" ""
+.RB "" "reauth_time" ""
+values, as it applies to both.
+
+The default is 10% of the longer of
+.RB "" "rekey_time" ""
+and
+.RB "" "reauth_time" "."
+
+
+.TP
+.BR connections.<conn>.rand_time " [over_time]"
+Time range from which to choose a random value to subtract from rekey/reauth
+times. To avoid having both peers initiating the rekey/reauth procedure
+simultaneously, a random time gets subtracted from the rekey/reauth times.
+
+The default is equal to the configured
+.RB "" "over_time" "."
+
+
+.TP
+.BR connections.<conn>.pools " []"
+Comma separated list of named IP pools to allocate virtual IP addresses and
+other configuration attributes from. Each name references a pool by name from
+either the
+.RB "" "pools" ""
+section or an external pool.
+
+.TP
+.B connections.<conn>.local<suffix>
+.br
+Section for a local authentication round. A local authentication round defines
+the rules how authentication is performed for the local peer. Multiple rounds
+may be defined to use IKEv2 RFC 4739 Multiple Authentication or IKEv1 XAuth.
+
+Each round is defined in a section having
+.RI "" "local" ""
+as prefix, and an optional
+unique suffix. To define a single authentication round, the suffix may be
+omitted.
+
+.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.
+
+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>.auth " [pubkey]"
+Authentication to perform locally.
+.RI "" "pubkey" ""
+uses public key authentication using
+a private key associated to a usable certificate.
+.RI "" "psk" ""
+uses pre\-shared key
+authentication. The IKEv1 specific
+.RI "" "xauth" ""
+is used for XAuth or Hybrid
+authentication, while the IKEv2 specific
+.RI "" "eap" ""
+keyword defines EAP
+authentication.
+
+For
+.RI "" "xauth" ","
+a specific backend name may be appended, separated by a dash. The
+appropriate
+.RI "" "xauth" ""
+backend is selected to perform the XAuth exchange. For
+traditional XAuth, the
+.RI "" "xauth" ""
+method is usually defined in the second
+authentication round following an initial
+.RI "" "pubkey" ""
+(or
+.RI "" "psk" ")"
+round. Using
+.RI "" "xauth" ""
+in the first round performs Hybrid Mode client authentication.
+
+For
+.RI "" "eap" ","
+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.
+
+.TP
+.BR connections.<conn>.local<suffix>.id " []"
+IKE identity to use for authentication round. When using certificate
+authentication, the IKE identity must be contained in the certificate, either as
+subject or as subjectAltName.
+
+.TP
+.BR connections.<conn>.local<suffix>.eap_id " [id]"
+Client EAP\-Identity to use in EAP\-Identity exchange and the EAP method.
+
+.TP
+.BR connections.<conn>.local<suffix>.aaa_id " [remote-id]"
+Server side EAP\-Identity to expect in the EAP method. Some EAP methods, such as
+EAP\-TLS, use an identity for the server to perform mutual authentication. This
+identity may differ from the IKE identity, especially when EAP authentication is
+delegated from the IKE responder to an AAA backend.
+
+For EAP\-(T)TLS, this defines the identity for which the server must provide a
+certificate in the TLS exchange.
+
+.TP
+.BR connections.<conn>.local<suffix>.xauth_id " [id]"
+Client XAuth username used in the XAuth exchange.
+
+.TP
+.B connections.<conn>.remote<suffix>
+.br
+Section for a remote authentication round. A remote authentication round defines
+the constraints how the peers must authenticate to use this connection. Multiple
+rounds may be defined to use IKEv2 RFC 4739 Multiple Authentication or IKEv1
+XAuth.
+
+Each round is defined in a section having
+.RI "" "remote" ""
+as prefix, and an optional
+unique suffix. To define a single authentication round, the suffix may be
+omitted.
+
+.TP
+.BR connections.<conn>.remote<suffix>.id " [%any]"
+IKE identity to expect for authentication round. When using certificate
+authentication, the IKE identity must be contained in the certificate, either as
+subject or as subjectAltName.
+
+.TP
+.BR connections.<conn>.remote<suffix>.groups " []"
+Comma separated authorization group memberships to require. The peer must prove
+membership to at least one of the specified groups. Group membership can be
+certified by different means, for example by appropriate Attribute Certificates
+or by an AAA backend involved in the authentication.
+
+.TP
+.BR connections.<conn>.remote<suffix>.certs " []"
+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.
+
+.TP
+.BR connections.<conn>.remote<suffix>.cacert " []"
+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
+an absolute path.
+
+.TP
+.BR connections.<conn>.remote<suffix>.revocation " [relaxed]"
+Certificate revocation policy for CRL or OCSP revocation.
+
+A
+.RI "" "strict" ""
+revocation policy fails if no revocation information is available,
+i.e. the certificate is not known to be unrevoked.
+
+.RI "" "ifuri" ""
+fails only if a CRL/OCSP URI is available, but certificate revocation
+checking fails, i.e. there should be revocation information available, but it
+could not be obtained.
+
+The default revocation policy
+.RI "" "relaxed" ""
+fails only if a certificate is revoked,
+i.e. it is explicitly known that it is bad.
+
+.TP
+.BR connections.<conn>.remote<suffix>.auth " [pubkey]"
+Authentication to expect from remote. See the
+.RB "" "local" ""
+sections
+.RB "" "auth" ""
+keyword description about the details of supported mechanisms.
+
+.TP
+.B connections.<conn>.children.<child>
+.br
+CHILD_SA configuration sub\-section. Each connection definition may have one or
+more sections in its
+.RI "" "children" ""
+subsection. The section name defines the name of
+the CHILD_SA configuration, which must be unique within the connection.
+
+.TP
+.BR connections.<conn>.children.<child>.ah_proposals " []"
+AH proposals to offer for the CHILD_SA. A proposal is a set of algorithms. For
+AH, this includes an integrity algorithm and an optional Diffie\-Hellman group.
+If a DH group is specified, CHILD_SA/Quick Mode rekeying and initial negotiation
+uses a separate Diffie\-Hellman exchange using the specified group.
+
+In IKEv2, multiple algorithms of the same kind can be specified in a single
+proposal, from which one gets selected. In IKEv1, only one algorithm per kind is
+allowed per proposal, more algorithms get implicitly stripped. Use multiple
+proposals to offer different algorithms combinations in IKEv1.
+
+Algorithm keywords get separated using dashes. Multiple proposals may be
+separated by commas. The special value
+.RI "" "default" ""
+forms a default proposal of
+supported algorithms considered safe, and is usually a good choice for
+interoperability. By default no AH proposals are included, instead ESP is
+proposed.
+
+.TP
+.BR connections.<conn>.children.<child>.esp_proposals " [default]"
+ESP proposals to offer for the CHILD_SA. A proposal is a set of algorithms. For
+ESP non\-AEAD proposals, this includes an integrity algorithm, an encryption
+algorithm, an optional Diffie\-Hellman group and an optional Extended Sequence
+Number Mode indicator. For AEAD proposals, a combined mode algorithm is used
+instead of the separate encryption/integrity algorithms.
+
+If a DH group is specified, CHILD_SA/Quick Mode rekeying and initial (non
+IKE_AUTH piggybacked) negotiation uses a separate Diffie\-Hellman exchange using
+the specified group. Extended Sequence Number support may be indicated with the
+.RI "" "esn" ""
+and
+.RI "" "noesn" ""
+values, both may be included to indicate support for both
+modes. If omitted,
+.RI "" "noesn" ""
+is assumed.
+
+In IKEv2, multiple algorithms of the same kind can be specified in a single
+proposal, from which one gets selected. In IKEv1, only one algorithm per kind is
+allowed per proposal, more algorithms get implicitly stripped. Use multiple
+proposals to offer different algorithms combinations in IKEv1.
+
+Algorithm keywords get separated using dashes. Multiple proposals may be
+separated by commas. The special value
+.RI "" "default" ""
+forms a default proposal of
+supported algorithms considered safe, and is usually a good choice for
+interoperability. If no algorithms are specified for AH nor ESP, the
+.RI "" "default" ""
+set of algorithms for ESP is included.
+
+.TP
+.BR connections.<conn>.children.<child>.local_ts " [dynamic]"
+Comma separated list of local traffic selectors to include in CHILD_SA. Each
+selector is a CIDR subnet definition, followed by an optional proto/port
+selector. The special value
+.RI "" "dynamic" ""
+may be used instead of a subnet
+definition, which gets replaced by the tunnel outer address or the virtual IP,
+if negotiated. This is the default.
+
+A protocol/port selector is surrounded by opening and closing square brackets.
+Between these brackets, a numeric or
+.RB "" "getservent" "(3)"
+protocol name may be
+specified. After the optional protocol restriction, an optional port restriction
+may be specified, separated by a slash. The port restriction may be numeric, a
+.RB "" "getservent" "(3)"
+service name, or the special value
+.RI "" "opaque" ""
+for RFC 4301
+OPAQUE selectors. Port ranges may be specified as well, none of the kernel
+backends currently support port ranges, though.
+
+Unless the Unity extension is used, IKEv1 supports the first specified selector
+only. IKEv1 uses very similar traffic selector narrowing as it is supported in
+the IKEv2 protocol.
+
+.TP
+.BR connections.<conn>.children.<child>.remote_ts " [dynamic]"
+Comma separated list of remote selectors to include in CHILD_SA. See
+.RB "" "local_ts" ""
+for a description of the selector syntax.
+
+.TP
+.BR connections.<conn>.children.<child>.rekey_time " [1h]"
+Time to schedule CHILD_SA rekeying. CHILD_SA rekeying refreshes key material,
+optionally using a Diffie\-Hellman exchange if a group is specified in the
+proposal.
+
+To avoid rekey collisions initiated by both ends simultaneously, a value in the
+range of
+.RB "" "rand_time" ""
+gets subtracted to form the effective soft lifetime.
+
+By default CHILD_SA rekeying is scheduled every hour, minus
+.RB "" "rand_time" "."
+
+
+.TP
+.BR connections.<conn>.children.<child>.life_time " [rekey_time + 10%]"
+Maximum lifetime before CHILD_SA gets closed. Usually this hard lifetime is
+never reached, because the CHILD_SA gets rekeyed before. If that fails for
+whatever reason, this limit closes the CHILD_SA.
+
+The default is 10% more than the
+.RB "" "rekey_time" "."
+
+
+.TP
+.BR connections.<conn>.children.<child>.rand_time " [life_time - rekey_time]"
+Time range from which to choose a random value to subtract from
+.RB "" "rekey_time" "."
+The default is the difference between
+.RB "" "life_time" ""
+and
+.RB "" "rekey_time" "."
+
+
+.TP
+.BR connections.<conn>.children.<child>.rekey_bytes " [0]"
+Number of bytes processed before initiating CHILD_SA rekeying. CHILD_SA rekeying
+refreshes key material, optionally using a Diffie\-Hellman exchange if a group is
+specified in the proposal.
+
+To avoid rekey collisions initiated by both ends simultaneously, a value in the
+range of
+.RB "" "rand_bytes" ""
+gets subtracted to form the effective soft volume limit.
+
+Volume based CHILD_SA rekeying is disabled by default.
+
+.TP
+.BR connections.<conn>.children.<child>.life_bytes " [rekey_bytes + 10%]"
+Maximum bytes processed before CHILD_SA gets closed. Usually this hard volume
+limit is never reached, because the CHILD_SA gets rekeyed before. If that fails
+for whatever reason, this limit closes the CHILD_SA.
+
+The default is 10% more than
+.RB "" "rekey_bytes" "."
+
+
+.TP
+.BR connections.<conn>.children.<child>.rand_bytes " [life_bytes - rekey_bytes]"
+Byte range from which to choose a random value to subtract from
+.RB "" "rekey_bytes" "."
+The default is the difference between
+.RB "" "life_bytes" ""
+and
+.RB "" "rekey_bytes" "."
+
+
+.TP
+.BR connections.<conn>.children.<child>.rekey_packets " [0]"
+Number of packets processed before initiating CHILD_SA rekeying. CHILD_SA
+rekeying refreshes key material, optionally using a Diffie\-Hellman exchange if a
+group is specified in the proposal.
+
+To avoid rekey collisions initiated by both ends simultaneously, a value in the
+range of
+.RB "" "rand_packets" ""
+gets subtracted to form the effective soft packet
+count limit.
+
+Packet count based CHILD_SA rekeying is disabled by default.
+
+.TP
+.BR connections.<conn>.children.<child>.life_packets " [rekey_packets + 10%]"
+Maximum number of packets processed before CHILD_SA gets closed. Usually this
+hard packets limit is never reached, because the CHILD_SA gets rekeyed before.
+If that fails for whatever reason, this limit closes the CHILD_SA.
+
+The default is 10% more than
+.RB "" "rekey_bytes" "."
+
+
+.TP
+.BR connections.<conn>.children.<child>.rand_packets " [life_packets - rekey_packets]"
+Packet range from which to choose a random value to subtract from
+.RB "" "rekey_packets" "."
+The default is the difference between
+.RB "" "life_packets" ""
+and
+.RB "" "rekey_packets" "."
+
+
+.TP
+.BR connections.<conn>.children.<child>.updown " []"
+Updown script to invoke on CHILD_SA up and down events.
+
+.TP
+.BR connections.<conn>.children.<child>.hostaccess " [yes]"
+Hostaccess variable to pass to
+.RB "" "updown" ""
+script.
+
+.TP
+.BR connections.<conn>.children.<child>.mode " [tunnel]"
+IPsec Mode to establish CHILD_SA with.
+.RI "" "tunnel" ""
+negotiates the CHILD_SA in IPsec
+Tunnel Mode, whereas
+.RI "" "transport" ""
+uses IPsec Transport Mode.
+.RI "" "beet" ""
+is the Bound
+End to End Tunnel mixture mode, working with fixed inner addresses without the
+need to include them in each packet.
+
+Both
+.RI "" "transport" ""
+and
+.RI "" "beet" ""
+modes are subject to mode negotiation;
+.RI "" "tunnel" ""
+mode
+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.
+
+.TP
+.BR connections.<conn>.children.<child>.dpd_action " [clear]"
+Action to perform for this CHILD_SA on DPD timeout. The default
+.RI "" "clear" ""
+closes
+the CHILD_SA and does not take further action.
+.RI "" "trap" ""
+installs a trap policy,
+which will catch matching traffic and tries to re\-negotiate the tunnel
+on\-demand.
+.RI "" "restart" ""
+immediately tries to re\-negotiate the CHILD_SA under a
+fresh IKE_SA.
+
+.TP
+.BR connections.<conn>.children.<child>.ipcomp " [no]"
+Enable IPComp compression before encryption. If enabled, IKE tries to negotiate
+IPComp compression to compress ESP payload data prior to encryption.
+
+.TP
+.BR connections.<conn>.children.<child>.inactivity " [0s]"
+Timeout before closing CHILD_SA after inactivity. If no traffic has been
+processed in either direction for the configured timeout, the CHILD_SA gets
+closed due to inactivity. The default value of
+.RI "" "0" ""
+disables inactivity checks.
+
+.TP
+.BR connections.<conn>.children.<child>.reqid " [0]"
+Fixed reqid to use for this CHILD_SA. This might be helpful in some scenarios,
+but works only if each CHILD_SA configuration is instantiated not more than
+once. The default of
+.RI "" "0" ""
+uses dynamic reqids, allocated incrementally.
+
+.TP
+.BR connections.<conn>.children.<child>.mark_in " [0/0x00000000]"
+Netfilter mark and mask for input traffic. On Linux Netfilter may apply marks to
+each packet coming from a tunnel having that option set. The mark may then be
+used by Netfilter to match rules.
+
+An additional mask may be appended to the mark, separated by _/_. The default
+mask if omitted is 0xffffffff.
+
+.TP
+.BR connections.<conn>.children.<child>.mark_out " [0/0x00000000]"
+Netfilter mark and mask for output traffic. On Linux Netfilter may require marks
+on each packet to match a policy having that option set. This allows Netfilter
+rules to select specific tunnels for outgoing traffic.
+
+An additional mask may be appended to the mark, separated by _/_. The default
+mask if omitted is 0xffffffff.
+
+.TP
+.BR connections.<conn>.children.<child>.tfc_padding " [0]"
+Pads ESP packets with additional data to have a consistent ESP packet size for
+improved Traffic Flow Confidentiality. The padding defines the minimum size of
+all ESP packets sent.
+
+The default value of 0 disables TFC padding, the special value
+.RI "" "mtu" ""
+adds TFC
+padding to create a packet size equal to the Path Maximum Transfer Unit.
+
+.TP
+.BR connections.<conn>.children.<child>.replay_window " [32]"
+IPsec replay window to configure for this CHILD_SA. Larger values than the
+default of 32 are supported using the Netlink backend only, a value of 0
+disables IPsec replay protection.
+
+.TP
+.BR connections.<conn>.children.<child>.start_action " [none]"
+Action to perform after loading the configuration. The default of
+.RI "" "none" ""
+loads
+the connection only, which then can be manually initiated or used as a responder
+configuration.
+
+The value
+.RI "" "trap" ""
+installs a trap policy, which triggers the tunnel as soon as
+matching traffic has been detected. The value
+.RI "" "start" ""
+initiates the connection
+actively.
+
+When unloading or replacing a CHILD_SA configuration having a
+.RB "" "start_action" ""
+different from
+.RI "" "none" ","
+the inverse action is performed. Configurations with
+.RI "" "start" ""
+get closed, while such with
+.RI "" "trap" ""
+get uninstalled.
+
+.TP
+.BR connections.<conn>.children.<child>.close_action " [none]"
+Action to perform after a CHILD_SA gets closed by the peer. The default of
+.RI "" "none" ""
+does not take any action,
+.RI "" "trap" ""
+installs a trap policy for the CHILD_SA.
+.RI "" "start" ""
+tries to re\-create the CHILD_SA.
+
+.RB "" "close_action" ""
+does not provide any guarantee that the CHILD_SA is kept alive.
+It acts on explicit close messages only, but not on negotiation failures. Use
+trap policies to reliably re\-create failed CHILD_SAs.
+
+.TP
+.B secrets
+.br
+Section defining secrets for IKE/EAP/XAuth authentication and private key
+decryption. The
+.RB "" "secrets" ""
+section takes sub\-sections having a specific prefix
+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.
+
+.TP
+.B secrets.eap<suffix>
+.br
+EAP secret section for a specific secret. Each EAP secret is defined in a unique
+section having the
+.RI "" "eap" ""
+prefix. EAP secrets are used for XAuth authentication
+as well.
+
+.TP
+.BR secrets.eap<suffix>.secret " []"
+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
+.RI "" "0s" ""
+prefix in its value.
+
+.TP
+.BR secrets.eap<suffix>.id<suffix> " []"
+Identity the EAP/XAuth secret belongs to. Multiple unique identities may be
+specified, each having an
+.RI "" "id" ""
+prefix, if a secret is shared between multiple
+users.
+
+.TP
+.B secrets.xauth<suffix>
+.br
+XAuth secret section for a specific secret.
+.RB "" "xauth" ""
+is just an alias for
+.RB "" "eap" ","
+secrets under both section prefixes are used for both EAP and XAuth
+authentication.
+
+.TP
+.B secrets.ike<suffix>
+.br
+IKE preshared secret section for a specific secret. Each IKE PSK is defined in a
+unique section having the
+.RI "" "ike" ""
+prefix.
+
+.TP
+.BR secrets.ike<suffix>.secret " []"
+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
+.RI "" "0s" ""
+prefix in its value.
+
+.TP
+.BR secrets.ike<suffix>.id<suffix> " []"
+IKE identity the IKE preshared secret belongs to. Multiple unique identities may
+be specified, each having an
+.RI "" "id" ""
+prefix, if a secret is shared between multiple
+peers.
+
+.TP
+.B secrets.rsa<suffix>
+.br
+Private key decryption passphrase for a key in the
+.RI "" "rsa" ""
+folder.
+
+.TP
+.BR secrets.rsa<suffix>.file " []"
+File name in the
+.RI "" "rsa" ""
+folder for which this passphrase should be used.
+
+.TP
+.BR secrets.rsa<suffix>.secret " []"
+Value of decryption passphrase for RSA key.
+
+.TP
+.B secrets.ecdsa<suffix>
+.br
+Private key decryption passphrase for a key in the
+.RI "" "ecdsa" ""
+folder.
+
+.TP
+.BR secrets.ecdsa<suffix>.file " []"
+File name in the
+.RI "" "ecdsa" ""
+folder for which this passphrase should be used.
+
+.TP
+.BR secrets.ecdsa<suffix>.secret " []"
+Value of decryption passphrase for ECDSA key.
+
+.TP
+.B secrets.pkcs8<suffix>
+.br
+Private key decryption passphrase for a key in the
+.RI "" "pkcs8" ""
+folder.
+
+.TP
+.BR secrets.pkcs8<suffix>.file " []"
+File name in the
+.RI "" "pkcs8" ""
+folder for which this passphrase should be used.
+
+.TP
+.BR secrets.pkcs8<suffix>.secret " []"
+Value of decryption passphrase for PKCS#8 key.
+
+.TP
+.B pools
+.br
+Section defining named pools. Named pools may be referenced by connections with
+the
+.RB "" "pools" ""
+option to assign virtual IPs and other configuration attributes.
+
+.TP
+.B pools.<name>
+.br
+Section defining a single pool with a unique name.
+
+.TP
+.BR pools.<name>.addrs " []"
+Subnet defining addresses allocated in pool. Accepts a single CIDR subnet
+defining the pool to allocate addresses from. Pools must be unique and
+non\-overlapping.
+
+.TP
+.BR pools.<name>.<attr> " []"
+Comma separated list of additional attributes of type
+.RB "" "<attr>" "."
+The attribute
+type may be one of
+.RI "" "dns" ","
+.RI "" "nbns" ","
+.RI "" "dhcp" ","
+.RI "" "netmask" ","
+.RI "" "server" ","
+.RI "" "subnet" ","
+.RI "" "split_include" ""
+and
+.RI "" "split_exclude" ""
+to define addresses or CIDR subnets for the
+corresponding attribute types. Alternatively,
+.RB "" "<attr>" ""
+can be a numerical
+identifier, for which string attribute values are accepted as well.
+
diff --git a/src/swanctl/swanctl.conf.5.tail.in b/src/swanctl/swanctl.conf.5.tail.in
new file mode 100644
index 0000000..4d24608
--- /dev/null
+++ b/src/swanctl/swanctl.conf.5.tail.in
@@ -0,0 +1,10 @@
+.SH FILES
+.
+.nf
+.na
+/etc/swanctl/swanctl.conf       configuration file
+.ad
+.fi
+.
+.SH SEE ALSO
+.BR swanctl (8)
diff --git a/src/swanctl/swanctl.h b/src/swanctl/swanctl.h
new file mode 100644
index 0000000..bd7e003
--- /dev/null
+++ b/src/swanctl/swanctl.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup swanctl swanctl
+ * @{
+ */
+
+#ifndef SWANCTL_H_
+#define SWANCTL_H_
+
+/**
+ * Configuration file for connections, etc.
+ */
+#define SWANCTL_CONF SWANCTLDIR "/swanctl.conf"
+
+/**
+ * Directory for X.509 end entity certs
+ */
+#define SWANCTL_X509DIR SWANCTLDIR "/x509"
+
+/**
+ * Directory for X.509 CA certs
+ */
+#define SWANCTL_X509CADIR SWANCTLDIR "/x509ca"
+
+/**
+ * Directory for X.509 Attribute Authority certs
+ */
+#define SWANCTL_X509AADIR SWANCTLDIR "/x509aa"
+
+/**
+ * Directory for X.509 CRLs
+ */
+#define SWANCTL_X509CRLDIR SWANCTLDIR "/x509crl"
+
+/**
+ * Directory for X.509 Attribute certificates
+ */
+#define SWANCTL_X509ACDIR SWANCTLDIR "/x509ac"
+
+/**
+ * Directory for RSA private keys
+ */
+#define SWANCTL_RSADIR SWANCTLDIR "/rsa"
+
+/**
+ * Directory for ECDSA private keys
+ */
+#define SWANCTL_ECDSADIR SWANCTLDIR "/ecdsa"
+
+/**
+ * Directory for PKCS#8 encoded private keys
+ */
+#define SWANCTL_PKCS8DIR SWANCTLDIR "/pkcs8"
+
+#endif /** SWANCTL_H_ @}*/
diff --git a/src/swanctl/swanctl.opt b/src/swanctl/swanctl.opt
new file mode 100644
index 0000000..e136ffb
--- /dev/null
+++ b/src/swanctl/swanctl.opt
@@ -0,0 +1,779 @@
+connections { # }
+	Section defining IKE connection configurations.
+
+	Section defining IKE connection configurations.
+
+	The connections section defines IKE connection configurations, each in
+	its own subsections. In the keyword description below, the connection
+	is named _<conn>_, but an arbitrary yet unique connection name can be
+	chosen for each connection subsection.
+
+connections.<conn> { # }
+	Section for an IKE connection named <conn>.
+
+connections.<conn>.version = 0
+	IKE major version to use for connection.
+
+	IKE major version to use for connection. _1_ uses IKEv1 aka ISAKMP, _2_
+	uses IKEv2. A connection using the default of _0_ accepts both IKEv1
+	and IKEv2 as responder, and initiates the connection actively with IKEv2.
+
+connections.<conn>.local_addrs = %any
+	Local address(es) to use for IKE communication, comma separated.
+
+	Local address(es) to use for IKE communication, comma separated. Takes
+	single IPv4/IPv6 addresses, DNS names, CIDR subnets or IP address ranges.
+
+	As initiator, the first non-range/non-subnet is used to initiate the
+	connection from. As responder, the local destination address must match at
+	least to one of the specified addresses, subnets or ranges.
+
+connections.<conn>.remote_addrs = %any
+	Remote address(es) to use for IKE communication, comma separated.
+
+	Remote address(es) to use for IKE communication, comma separated. Takes
+	single IPv4/IPv6 addresses, DNS names, CIDR subnets or IP address ranges.
+
+	As initiator, the first non-range/non-subnet is used to initiate the
+	connection to. As responder, the initiator source address must match at
+	least to one of the specified addresses, subnets or ranges.
+
+	To initiate a connection, at least one specific address or DNS name must
+	be specified.
+
+connections.<conn>.local_port = 500
+	Local UPD port for IKE communication.
+
+	Local UPD 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.
+
+	Using a non-default local IKE port requires support from the socket backend
+	in use (socket-dynamic).
+
+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,
+	automatic IKE port floating to port 4500 is used to work around NAT issues.
+
+connections.<conn>.proposals = default
+	Comma separated proposals to accept for IKE.
+
+	A proposal is a set of algorithms. For non-AEAD algorithms, this includes
+	for IKE an encryption algorithm, an integrity algorithm, a pseudo random
+	function and a Diffie-Hellman group. For AEAD algorithms, instead of
+	encryption and integrity algorithms, a combined algorithm is used.
+
+	In IKEv2, multiple algorithms of the same kind can be specified in a single
+	proposal, from which one gets selected. In IKEv1, only one algorithm per
+	kind is allowed per proposal, more algorithms get implicitly stripped. Use
+	multiple proposals to offer different algorithms combinations in IKEv1.
+
+	Algorithm keywords get separated using dashes. Multiple proposals may be
+	separated by commas. The special value _default_ forms a default proposal
+	of supported algorithms considered safe, and is usually a good choice
+	for interoperability.
+
+connections.<conn>.vips =
+	Virtual IPs to request in configuration payload / Mode Config.
+
+	Comma separated list of virtual IPs to request in IKEv2 configuration
+	payloads or IKEv1 Mode Config. The wildcard addresses _0.0.0.0_ and _::_
+	request an arbitrary address, specific addresses may be defined. The
+	responder may return a different address, though, or none at all.
+
+connections.<conn>.aggressive = no
+	Use Aggressive Mode in IKEv1.
+
+	Enables Aggressive Mode instead of Main Mode with Identity Protection.
+	Aggressive Mode is considered less secure, because the ID and HASH
+	payloads are exchanged unprotected. This allows a passive attacker to
+	snoop peer identities, and even worse, start dictionary attacks on the
+	Preshared Key.
+
+connections.<conn>.pull = yes
+	Set the Mode Config mode to use.
+
+	If the default of _yes_ is used, Mode Config works in pull mode, where
+	the initiator actively requests a virtual IP. With _no_, push mode is used,
+	where the responder pushes down a virtual IP to the initiating peer.
+
+	Push mode is currently supported for IKEv1, but not in IKEv2. It is used
+	by a few implementations only, pull mode is recommended.
+
+connections.<conn>.encap = no
+	Enforce UDP encapsulation by faking NAT-D payloads.
+
+	To enforce UDP encapsulation of ESP packets, the IKE daemon can fake the
+	NAT detection payloads. This makes the peer believe that NAT takes
+	place on the path, forcing it to encapsulate ESP packets in UDP.
+
+	Usually this is not required, but it can help to work around connectivity
+	issues with too restrictive intermediary firewalls.
+
+connections.<conn>.mobike = yes
+	Enables MOBIKE on IKEv2 connections.
+
+	Enables MOBIKE on IKEv2 connections. MOBIKE is enabled by default on IKEv2
+	connections, and allows mobility of clients and multi-homing on servers by
+	migrating active IPsec tunnels.
+
+	Usually keeping MOBIKE enabled is unproblematic, as it is not used if the
+	peer does not indicate support for it. However, due to the design of MOBIKE,
+	IKEv2 always floats to port 4500 starting from the second exchange. Some
+	implementations don't like this behavior, hence it can be disabled.
+
+connections.<conn>.dpd_delay = 0s
+	Interval of liveness checks (DPD).
+
+	Interval to check the liveness of a peer actively using IKEv2 INFORMATIONAL
+	exchanges or IKEv1 R_U_THERE messages. Active DPD checking is only enforced
+	if no IKE or ESP/AH packet has been received for the configured DPD delay.
+
+connections.<conn>.dpd_timeout = 0s
+	Timeout for DPD checks (IKEV1 only).
+
+	Charon by default uses the normal retransmission mechanism and timeouts to
+	check the liveness of a peer, as all messages are used for liveness
+	checking. For compatibility reasons, with IKEv1 a custom interval may be
+	specified; this option has no effect on connections using IKE2.
+
+connections.<conn>.fragmentation = no
+	Use IKEv1 UDP packet 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.
+
+connections.<conn>.send_certreq = yes
+	Send certificate requests payloads (_yes_ or _no_).
+
+	Send certificate request payloads to offer trusted root CA certificates
+	to the peer. Certificate requests help the peer to choose an appropriate
+	certificate/private key for authentication and are enabled by default.
+
+	Disabling certificate requests can be useful if too many trusted root CA
+	certificates are installed, as each certificate request increases the size
+	of the initial IKE packets.
+
+connections.<conn>.send_cert = ifasked
+	Send certificate payloads (_yes_, _no_ or _ifasked_).
+
+	Send certificate payloads when using certificate authentication. With the
+	default of _ifasked_ the daemon sends certificate payloads only if
+	certificate requests have been received. _no_ disables sending of
+	certificate payloads, _yes_ always sends certificate payloads whenever
+	certificate authentication is used.
+
+connections.<conn>.keyingtries = 1
+	Number of retransmission sequences to perform during initial connect.
+
+	Number of retransmission sequences to perform during initial connect.
+	Instead of giving up initiation after the first retransmission sequence with
+	the default value of _1_, additional sequences may be started according to
+	the configured value. A value of _0_ initiates a new sequence until the
+	connection establishes or fails with a permanent error.
+
+connections.<conn>.unique = no
+	Connection uniqueness policy (_never_, _no_, _keep_ or _replace_).
+
+	Connection uniqueness policy to enforce. To avoid multiple connections
+	from the same user, a uniqueness policy can be enforced. The value _never_
+	does never enforce such a policy, even if a peer included INITIAL_CONTACT
+	notification messages, whereas _no_ replaces existing connections for the
+	same identity if a new one has the INITIAL_CONTACT notify. _keep_ rejects
+	new connection attempts if the same user already has an active connection,
+	_replace_ deletes any existing connection if a new one for the same user
+	gets established.
+
+	To compare connections for uniqueness, the remote IKE identity is used. If
+	EAP or XAuth authentication is involved, the EAP-Identity or XAuth username
+	is used to enforce the uniqueness policy instead.
+
+connections.<conn>.reauth_time = 0s
+	Time to schedule IKE reauthentication.
+
+	Time to schedule IKE reauthentication. IKE reauthentication recreates the
+	IKE/ISAKMP SA from scratch and re-evaluates the credentials. In asymmetric
+	configurations (with EAP or configuration payloads) it might not be possible
+	to actively reauthenticate as responder. The IKEv2 reauthentication lifetime
+	negotiation can instruct the client to perform reauthentication.
+
+	Reauthentication is disabled by default. Enabling it usually may lead
+	to small connection interruptions, as strongSwan uses a break-before-make
+	policy with IKEv2 to avoid any conflicts with associated tunnel resources.
+
+connections.<conn>.rekey_time = 4h
+	Time to schedule IKE rekeying.
+
+	IKE rekeying refreshes key material using a Diffie-Hellman exchange, but
+	does not re-check associated credentials. It is supported in IKEv2 only,
+	IKEv1 performs a reauthentication procedure instead.
+
+	With the default value IKE rekeying is scheduled every 4 hours, minus the
+	configured **rand_time**.
+
+connections.<conn>.over_time = 10% of rekey_time/reauth_time
+	Hard IKE_SA lifetime if rekey/reauth does not complete, as time.
+
+	Hard IKE_SA lifetime if rekey/reauth does not complete, as time.
+	To avoid having an IKE/ISAKMP kept alive if IKE reauthentication or rekeying
+	fails perpetually, a maximum hard lifetime may be specified. If the
+	IKE_SA fails to rekey or reauthenticate within the specified time, the
+	IKE_SA gets closed.
+
+	In contrast to CHILD_SA rekeying, **over_time** is relative in time to the
+	**rekey_time** _and_ **reauth_time** values, as it applies to both.
+
+	The default is 10% of the longer of **rekey_time** and **reauth_time**.
+
+connections.<conn>.rand_time = over_time
+	Range of random time to subtract from rekey/reauth times.
+
+	Time range from which to choose a random value to subtract from
+	rekey/reauth times. To avoid having both peers initiating the rekey/reauth
+	procedure simultaneously, a random time gets subtracted from the
+	rekey/reauth times.
+
+	The default is equal to the configured **over_time**.
+
+connections.<conn>.pools =
+	Comma separated list of named IP pools.
+
+	Comma separated list of named IP pools to allocate virtual IP addresses and
+	other configuration attributes from. Each name references a pool by name
+	from either the **pools** section or an external pool.
+
+connections.<conn>.local<suffix> {}
+	Section for a local authentication round.
+
+	Section for a local authentication round. A local authentication round
+	defines the rules how authentication is performed for the local peer.
+	Multiple rounds may be defined to use IKEv2 RFC 4739 Multiple Authentication
+	or IKEv1 XAuth.
+
+	Each round is defined in a section having _local_ as prefix, and an optional
+	unique suffix. To define a single authentication round, the suffix may be
+	omitted.
+
+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.
+
+	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>.auth = pubkey
+	Authentication to perform locally (_pubkey_, _psk_, _xauth[-backend]_ or
+	_eap[-method]_).
+
+	Authentication to perform locally. _pubkey_ uses public key authentication
+	using a private key associated to a usable certificate. _psk_ uses
+	pre-shared key authentication. The IKEv1 specific _xauth_ is used for
+	XAuth or Hybrid authentication, while the IKEv2 specific _eap_ keyword
+	defines EAP authentication.
+
+	For _xauth_, a specific backend name may be appended, separated by a dash.
+	The appropriate _xauth_ backend is selected to perform the XAuth exchange.
+	For traditional XAuth, the _xauth_ method is usually defined in the second
+	authentication round following an initial _pubkey_ (or _psk_) round. Using
+	_xauth_ in the first round performs Hybrid Mode client authentication.
+
+	For _eap_, 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.
+
+connections.<conn>.local<suffix>.id =
+	IKE identity to use for authentication round.
+
+	IKE identity to use for authentication round. When using certificate
+	authentication, the IKE identity must be contained in the certificate,
+	either as subject or as subjectAltName.
+
+connections.<conn>.local<suffix>.eap_id = id
+	Client EAP-Identity to use in EAP-Identity exchange and the EAP method.
+
+connections.<conn>.local<suffix>.aaa_id = remote-id
+	Server side EAP-Identity to expect in the EAP method.
+
+	Server side EAP-Identity to expect in the EAP method. Some EAP methods, such
+	as EAP-TLS, use an identity for the server to perform mutual authentication.
+	This identity may differ from the IKE identity, especially when EAP
+	authentication is delegated from the IKE responder to an AAA backend.
+
+	For EAP-(T)TLS, this defines the identity for which the server must provide
+	a certificate in the TLS exchange.
+
+connections.<conn>.local<suffix>.xauth_id = id
+	Client XAuth username used in the XAuth exchange.
+
+connections.<conn>.remote<suffix> {}
+	Section for a remote authentication round.
+
+	Section for a remote authentication round. A remote authentication round
+	defines the constraints how the peers must authenticate to use this
+	connection. Multiple rounds may be defined to use IKEv2 RFC 4739 Multiple
+	Authentication or IKEv1 XAuth.
+
+	Each round is defined in a section having _remote_ as prefix, and an
+	optional unique suffix. To define a single authentication round, the suffix
+	may be omitted.
+
+connections.<conn>.remote<suffix>.id = %any
+	IKE identity to expect for authentication round.
+
+	IKE identity to expect for authentication round. When using certificate
+	authentication, the IKE identity must be contained in the certificate,
+	either as subject or as subjectAltName.
+
+connections.<conn>.remote<suffix>.groups =
+	Authorization group memberships to require.
+
+	Comma separated authorization group memberships to require. The peer must
+	prove membership to at least one of the specified groups. Group membership
+	can be certified by different means, for example by appropriate Attribute
+	Certificates or by an AAA backend involved in the authentication.
+
+connections.<conn>.remote<suffix>.certs =
+	Comma separated list of certificate to accept for authentication.
+
+	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.
+
+connections.<conn>.remote<suffix>.cacert =
+	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.
+
+connections.<conn>.remote<suffix>.revocation = relaxed
+	Certificate revocation policy, (_strict_, _ifuri_ or _relaxed_).
+
+	Certificate revocation policy for CRL or OCSP revocation.
+
+	A _strict_ revocation policy fails if no revocation information is
+	available, i.e. the certificate is not known to be unrevoked.
+
+	_ifuri_ fails only if a CRL/OCSP URI is available, but certificate
+	revocation checking fails, i.e. there should be revocation information
+	available, but it could not be obtained.
+
+	The default revocation policy _relaxed_ fails only if a certificate
+	is revoked, i.e. it is explicitly known that it is bad.
+
+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**
+	keyword description about the details of supported mechanisms.
+
+connections.<conn>.children.<child> {}
+	CHILD_SA configuration sub-section.
+
+	CHILD_SA configuration sub-section. Each connection definition may have
+	one or more sections in its _children_ subsection. The section name
+	defines the name of the CHILD_SA configuration, which must be unique within
+	the connection.
+
+connections.<conn>.children.<child>.ah_proposals =
+	AH proposals to offer for the CHILD_SA.
+
+	AH proposals to offer for the CHILD_SA. A proposal is a set of algorithms.
+	For AH, this includes an integrity algorithm and an optional Diffie-Hellman
+	group. If a DH group is specified, CHILD_SA/Quick Mode rekeying and initial
+	negotiation uses a separate Diffie-Hellman exchange using the specified
+	group.
+
+	In IKEv2, multiple algorithms of the same kind can be specified in a single
+	proposal, from which one gets selected. In IKEv1, only one algorithm per
+	kind is allowed per proposal, more algorithms get implicitly stripped. Use
+	multiple proposals to offer different algorithms combinations in IKEv1.
+
+	Algorithm keywords get separated using dashes. Multiple proposals may be
+	separated by commas. The special value _default_ forms a default proposal
+	of supported algorithms considered safe, and is usually a good choice
+	for interoperability. By default no AH proposals are included, instead ESP
+	is proposed.
+
+connections.<conn>.children.<child>.esp_proposals = default
+	ESP proposals to offer for the CHILD_SA.
+
+	ESP proposals to offer for the CHILD_SA. A proposal is a set of algorithms.
+	For ESP non-AEAD proposals, this includes an integrity algorithm, an
+	encryption algorithm, an optional Diffie-Hellman group and an optional
+	Extended Sequence Number Mode indicator. For AEAD proposals, a combined
+	mode algorithm is used instead of the separate encryption/integrity
+	algorithms.
+
+	If a DH group is specified, CHILD_SA/Quick Mode rekeying and initial (non
+	IKE_AUTH piggybacked) negotiation uses a separate Diffie-Hellman exchange
+	using the specified group. Extended Sequence Number support may be indicated
+	with the _esn_ and _noesn_ values, both may be included to indicate support
+	for both modes. If omitted, _noesn_ is assumed.
+
+	In IKEv2, multiple algorithms of the same kind can be specified in a single
+	proposal, from which one gets selected. In IKEv1, only one algorithm per
+	kind is allowed per proposal, more algorithms get implicitly stripped. Use
+	multiple proposals to offer different algorithms combinations in IKEv1.
+
+	Algorithm keywords get separated using dashes. Multiple proposals may be
+	separated by commas. The special value _default_ forms a default proposal
+	of supported algorithms considered safe, and is usually a good choice
+	for interoperability. If no algorithms are specified for AH nor ESP,
+	the _default_ set of algorithms for ESP is included.
+
+connections.<conn>.children.<child>.local_ts = dynamic
+	Local traffic selectors to include in CHILD_SA.
+
+	Comma separated list of local traffic selectors to include in CHILD_SA.
+	Each selector is a CIDR subnet definition, followed by an optional
+	proto/port selector. The special value _dynamic_ may be used instead of a
+	subnet definition, which gets replaced by the tunnel outer address or the
+	virtual IP, if negotiated. This is the default.
+
+	A protocol/port selector is surrounded by opening and closing square
+	brackets. Between these brackets, a numeric or **getservent**(3) protocol
+	name may be specified. After the optional protocol restriction, an optional
+	port restriction may be specified, separated by a slash. The port
+	restriction may be numeric, a **getservent**(3) service name, or the special
+	value _opaque_ for RFC 4301 OPAQUE selectors. Port ranges may be specified
+	as well, none of the kernel backends currently support port ranges, though.
+
+	Unless the Unity extension is used, IKEv1 supports the first specified
+	selector only. IKEv1 uses very similar traffic selector narrowing as it is
+	supported in the IKEv2 protocol.
+
+connections.<conn>.children.<child>.remote_ts = dynamic
+	Remote selectors to include in CHILD_SA.
+
+	Comma separated list of remote selectors to include in CHILD_SA. See
+	**local_ts** for a description of the selector syntax.
+
+connections.<conn>.children.<child>.rekey_time = 1h
+	Time to schedule CHILD_SA rekeying.
+
+	Time to schedule CHILD_SA rekeying. CHILD_SA rekeying refreshes key
+	material, optionally using a Diffie-Hellman exchange if a group is
+	specified in the proposal.
+
+	To avoid rekey collisions initiated by both ends simultaneously, a value
+	in the range of **rand_time** gets subtracted to form the effective soft
+	lifetime.
+
+	By default CHILD_SA rekeying is scheduled every hour, minus **rand_time**.
+
+connections.<conn>.children.<child>.life_time = rekey_time + 10%
+	Maximum lifetime before CHILD_SA gets closed, as time.
+
+	Maximum lifetime before CHILD_SA gets closed. Usually this hard lifetime
+	is never reached, because the CHILD_SA gets rekeyed before.
+	If that fails for whatever reason, this limit closes the CHILD_SA.
+
+	The default is 10% more than the **rekey_time**.
+
+connections.<conn>.children.<child>.rand_time = life_time - rekey_time
+	Range of random time to subtract from **rekey_time**.
+
+	Time range from which to choose a random value to subtract from
+	**rekey_time**. The default is the difference between **life_time** and
+	**rekey_time**.
+
+connections.<conn>.children.<child>.rekey_bytes = 0
+	Number of bytes processed before initiating CHILD_SA rekeying.
+
+	Number of bytes processed before initiating CHILD_SA rekeying. CHILD_SA
+	rekeying refreshes key material, optionally using a Diffie-Hellman exchange
+	if a group is specified in the proposal.
+
+	To avoid rekey collisions initiated by both ends simultaneously, a value
+	in the range of **rand_bytes** gets subtracted to form the effective soft
+	volume limit.
+
+	Volume based CHILD_SA rekeying is disabled by default.
+
+connections.<conn>.children.<child>.life_bytes = rekey_bytes + 10%
+	Maximum bytes processed before CHILD_SA gets closed.
+
+	Maximum bytes processed before CHILD_SA gets closed. Usually this hard
+	volume limit is never reached, because the CHILD_SA gets rekeyed before.
+	If that fails for whatever reason, this limit closes the CHILD_SA.
+
+	The default is 10% more than **rekey_bytes**.
+
+connections.<conn>.children.<child>.rand_bytes = life_bytes - rekey_bytes
+	Range of random bytes to subtract from **rekey_bytes**.
+
+	Byte range from which to choose a random value to subtract from
+	**rekey_bytes**. The default is the difference between **life_bytes** and
+	**rekey_bytes**.
+
+connections.<conn>.children.<child>.rekey_packets = 0
+	Number of packets processed before initiating CHILD_SA rekeying.
+
+	Number of packets processed before initiating CHILD_SA rekeying. CHILD_SA
+	rekeying refreshes key material, optionally using a Diffie-Hellman exchange
+	if a group is specified in the proposal.
+
+	To avoid rekey collisions initiated by both ends simultaneously, a value
+	in the range of **rand_packets** gets subtracted to form the effective soft
+	packet count limit.
+
+	Packet count based CHILD_SA rekeying is disabled by default.
+
+connections.<conn>.children.<child>.life_packets = rekey_packets + 10%
+	Maximum number of packets processed before CHILD_SA gets closed.
+
+	Maximum number of packets processed before CHILD_SA gets closed. Usually
+	this hard packets limit is never reached, because the CHILD_SA gets rekeyed
+	before. If that fails for whatever reason, this limit closes the CHILD_SA.
+
+	The default is 10% more than **rekey_bytes**.
+
+connections.<conn>.children.<child>.rand_packets = life_packets - rekey_packets
+	Range of random packets to subtract from **packets_bytes**.
+
+	Packet range from which to choose a random value to subtract from
+	**rekey_packets**. The default is the difference between **life_packets**
+	and **rekey_packets**.
+
+connections.<conn>.children.<child>.updown =
+	Updown script to invoke on CHILD_SA up and down events.
+
+connections.<conn>.children.<child>.hostaccess = yes
+	Hostaccess variable to pass to **updown** script.
+
+connections.<conn>.children.<child>.mode = tunnel
+	IPsec Mode to establish (_tunnel_, _transport_, _beet_, _pass_ or _drop_).
+
+	IPsec Mode to establish CHILD_SA with. _tunnel_ negotiates the CHILD_SA
+	in IPsec Tunnel Mode, whereas _transport_ uses IPsec Transport Mode. _beet_
+	is the Bound End to End Tunnel mixture mode, working with fixed inner
+	addresses without the need to include them in each packet.
+
+	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.
+
+connections.<conn>.children.<child>.dpd_action = clear
+	Action to perform on DPD timeout (_clear_, _trap_ or _restart_).
+
+	Action to perform for this CHILD_SA on DPD timeout. The default _clear_
+	closes the CHILD_SA and does not take further action. _trap_ installs
+	a trap policy, which will catch matching traffic and tries to re-negotiate
+	the tunnel on-demand. _restart_ immediately tries to re-negotiate the
+	CHILD_SA under a fresh IKE_SA.
+
+connections.<conn>.children.<child>.ipcomp = no
+	Enable IPComp compression before encryption.
+
+	Enable IPComp compression before encryption. If enabled, IKE tries to
+	negotiate IPComp compression to compress ESP payload data prior to
+	encryption.
+
+connections.<conn>.children.<child>.inactivity = 0s
+	Timeout before closing CHILD_SA after inactivity.
+
+	Timeout before closing CHILD_SA after inactivity. If no traffic has
+	been processed in either direction for the configured timeout, the CHILD_SA
+	gets closed due to inactivity. The default value of _0_ disables inactivity
+	checks.
+
+connections.<conn>.children.<child>.reqid = 0
+	Fixed reqid to use for this CHILD_SA.
+
+	Fixed reqid to use for this CHILD_SA. This might be helpful in some
+	scenarios, but works only if each CHILD_SA configuration is instantiated
+	not more than once. The default of _0_ uses dynamic reqids, allocated
+	incrementally.
+
+connections.<conn>.children.<child>.mark_in = 0/0x00000000
+	Netfilter mark and mask for input traffic.
+
+	Netfilter mark and mask for input traffic. On Linux Netfilter may apply
+	marks to each packet coming from a tunnel having that option set. The
+	mark may then be used by Netfilter to match rules.
+
+	An additional mask may be appended to the mark, separated by _/_. The
+	default mask if omitted is 0xffffffff.
+
+connections.<conn>.children.<child>.mark_out = 0/0x00000000
+	Netfilter mark and mask for output traffic.
+
+	Netfilter mark and mask for output traffic. On Linux Netfilter may require
+	marks on each packet to match a policy having that option set. This allows
+	Netfilter rules to select specific tunnels for outgoing traffic.
+
+	An additional mask may be appended to the mark, separated by _/_. The
+	default mask if omitted is 0xffffffff.
+
+connections.<conn>.children.<child>.tfc_padding = 0
+	Traffic Flow Confidentiality padding.
+
+	Pads ESP packets with additional data to have a consistent ESP packet size
+	for improved Traffic Flow Confidentiality. The padding defines the minimum
+	size of all ESP packets sent.
+
+	The default value of 0 disables TFC padding, the special value _mtu_ adds
+	TFC padding to create a packet size equal to the Path Maximum Transfer Unit.
+
+connections.<conn>.children.<child>.replay_window = 32
+	IPsec replay window to configure for this CHILD_SA.
+
+	IPsec replay window to configure for this CHILD_SA. Larger values than the
+	default of 32 are supported using the Netlink backend only, a value of 0
+	disables IPsec replay protection.
+
+connections.<conn>.children.<child>.start_action = none
+	Action to perform after loading the configuration (_none_, _trap_, _start_).
+
+	Action to perform after loading the configuration. The default of _none_
+	loads the connection only, which then can be manually initiated or used as
+	a responder configuration.
+
+	The value _trap_ installs a trap policy, which triggers the tunnel as soon
+	as matching traffic has been detected. The value _start_ initiates
+	the connection actively.
+
+	When unloading or replacing a CHILD_SA configuration having a
+	**start_action** different from _none_, the inverse action is performed.
+	Configurations with _start_ get closed, while such with _trap_ get
+	uninstalled.
+
+connections.<conn>.children.<child>.close_action = none
+	Action to perform after a CHILD_SA gets closed (_none_, _trap_, _start_).
+
+	Action to perform after a CHILD_SA gets closed by the peer. The default of
+	_none_ does not take any action, _trap_ installs a trap policy for the
+	CHILD_SA. _start_ tries to re-create the CHILD_SA.
+
+	**close_action** does not provide any guarantee that the CHILD_SA is kept
+	alive. It acts on explicit close messages only, but not on negotiation
+	failures. Use trap policies to reliably re-create failed CHILD_SAs.
+
+secrets { # }
+	Section defining secrets for IKE/EAP/XAuth authentication and private
+	key decryption.
+
+	Section defining secrets for IKE/EAP/XAuth authentication and private key
+	decryption. The **secrets** section takes sub-sections having a specific
+	prefix 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.
+
+secrets.eap<suffix> { # }
+	EAP secret section for a specific secret.
+
+	EAP secret section for a specific secret. Each EAP secret is defined in
+	a unique section having the _eap_ prefix. EAP secrets are used for XAuth
+	authentication as well.
+
+secrets.xauth<suffix> { # }
+	XAuth secret section for a specific secret.
+
+	XAuth secret section for a specific secret. **xauth** is just an alias
+	for **eap**, secrets under both section prefixes are used for both EAP and
+	XAuth authentication.
+
+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
+	has a _0s_ prefix in its value.
+
+secrets.eap<suffix>.id<suffix> =
+	Identity the EAP/XAuth secret belongs to.
+
+	Identity the EAP/XAuth secret belongs to. Multiple unique identities may
+	be specified, each having an _id_ prefix, if a secret is shared between
+	multiple users.
+
+secrets.ike<suffix> { # }
+	IKE preshared secret section for a specific secret.
+
+	IKE preshared secret section for a specific secret. Each IKE PSK is defined
+	in a unique section having the _ike_ prefix.
+
+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
+	it has a _0s_ prefix in its value.
+
+secrets.ike<suffix>.id<suffix> =
+	IKE identity the IKE preshared secret belongs to.
+
+	IKE identity the IKE preshared secret belongs to. Multiple unique identities
+	may be specified, each having an _id_ prefix, if a secret is shared between
+	multiple peers.
+
+secrets.rsa<suffix> { # }
+	Private key decryption passphrase for a key in the _rsa_ folder.
+
+secrets.rsa<suffix>.file =
+	File name in the _rsa_ folder for which this passphrase should be used.
+
+secrets.rsa<suffix>.secret
+	Value of decryption passphrase for RSA key.
+
+secrets.ecdsa<suffix> { # }
+	Private key decryption passphrase for a key in the _ecdsa_ folder.
+
+secrets.ecdsa<suffix>.file =
+	File name in the _ecdsa_ folder for which this passphrase should be used.
+
+secrets.ecdsa<suffix>.secret
+	Value of decryption passphrase for ECDSA key.
+
+secrets.pkcs8<suffix> { # }
+	Private key decryption passphrase for a key in the _pkcs8_ folder.
+
+secrets.pkcs8<suffix>.file =
+	File name in the _pkcs8_ folder for which this passphrase should be used.
+
+secrets.pkcs8<suffix>.secret
+	Value of decryption passphrase for PKCS#8 key.
+
+pools { # }
+	Section defining named pools.
+
+	Section defining named pools. Named pools may be referenced by connections
+	with the **pools** option to assign virtual IPs and other configuration
+	attributes.
+
+pools.<name> { # }
+	Section defining a single pool with a unique name.
+
+pools.<name>.addrs =
+	Subnet defining addresses allocated in pool.
+
+	Subnet defining addresses allocated in pool. Accepts a single CIDR subnet
+	defining the pool to allocate addresses from. Pools must be unique and
+	non-overlapping.
+
+pools.<name>.<attr> =
+	Comma separated list of additional attributes from type <attr>.
+
+	Comma separated list of additional attributes of type **<attr>**. The
+	attribute type may be one of _dns_, _nbns_, _dhcp_, _netmask_, _server_,
+	_subnet_, _split_include_ and _split_exclude_ to define addresses or CIDR
+	subnets for the corresponding attribute types. Alternatively, **<attr>** can
+	be a numerical identifier, for which string attribute values are accepted
+	as well.
diff --git a/testing/Makefile.in b/testing/Makefile.in
index f9acc24..ced07a4 100644
--- a/testing/Makefile.in
+++ b/testing/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -179,6 +179,7 @@ NM = @NM@
 NMEDIT = @NMEDIT@
 OBJDUMP = @OBJDUMP@
 OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
 PACKAGE = @PACKAGE@
@@ -197,6 +198,7 @@ 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@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -224,6 +226,7 @@ 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@
@@ -315,6 +318,7 @@ srcdir = @srcdir@
 starter_plugins = @starter_plugins@
 strongswan_conf = @strongswan_conf@
 strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 t_plugins = @t_plugins@
diff --git a/testing/config/kernel/config-3.15 b/testing/config/kernel/config-3.15
new file mode 100644
index 0000000..84f71da
--- /dev/null
+++ b/testing/config/kernel/config-3.15
@@ -0,0 +1,2083 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86 3.15.1 Kernel Configuration
+#
+CONFIG_64BIT=y
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ZONE_DMA32=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_SUPPORTS_INT128=y
+CONFIG_ARCH_WANTS_PROT_NUMA_PROT_NONE=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+# CONFIG_EXPERT is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_SOFT_DIRTY=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_SMP is not set
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_INTEL_LPSS is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+# CONFIG_HYPERVISOR_GUEST is not set
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_MCORE2=y
+# CONFIG_MATOM is not set
+# CONFIG_GENERIC_CPU is not set
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_P6_NOP=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_HPET_TIMER=y
+CONFIG_DMI=y
+CONFIG_GART_IOMMU=y
+# CONFIG_CALGARY_IOMMU is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_NR_CPUS=1
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+# CONFIG_X86_MCE is not set
+# CONFIG_I8K is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_MICROCODE_INTEL_EARLY is not set
+# CONFIG_MICROCODE_AMD_EARLY is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_DIRECT_GBPAGES=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_MEMORY_PROBE=y
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_MEMORY_ISOLATION=y
+CONFIG_HAVE_BOOTMEM_INFO_NODE=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+# CONFIG_COMPACTION is not set
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+# CONFIG_CMA is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=64
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+CONFIG_ARCH_RANDOM=y
+CONFIG_X86_SMAP=y
+# CONFIG_EFI is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_RELOCATABLE=y
+# CONFIG_RANDOMIZE_BASE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+# CONFIG_ACPI_PROCFS_POWER is not set
+# CONFIG_ACPI_EC_DEBUGFS is not set
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+# CONFIG_ACPI_HOTPLUG_MEMORY is not set
+# CONFIG_ACPI_SBS is not set
+# CONFIG_ACPI_HED is not set
+# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
+# CONFIG_ACPI_APEI is not set
+# CONFIG_SFI is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+# CONFIG_INTEL_IDLE is not set
+
+#
+# Memory power savings
+#
+# CONFIG_I7300_IDLE is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+# CONFIG_PCI_MMCONFIG is not set
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+# CONFIG_PCI_IOAPIC is not set
+CONFIG_PCI_LABEL=y
+
+#
+# PCI host controller drivers
+#
+CONFIG_ISA_DMA_API=y
+CONFIG_AMD_NB=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+# CONFIG_X86_SYSFB is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+# CONFIG_IA32_EMULATION is not set
+CONFIG_X86_DEV_DMA_OPS=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_XFRM_IPCOMP=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_ROUTE_CLASSID=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_ZONES is not set
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+CONFIG_NF_CT_PROTO_UDPLITE=y
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+# CONFIG_NF_CONNTRACK_FTP is not set
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+CONFIG_NF_CONNTRACK_SANE=y
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+CONFIG_NF_CT_NETLINK=y
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PROTO_UDPLITE=y
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_FTP is not set
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_TABLES is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_SET=y
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CT=y
+CONFIG_NETFILTER_XT_TARGET_DSCP=y
+CONFIG_NETFILTER_XT_TARGET_HL=y
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NETMAP=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=y
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ECN=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_HL=y
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_L2TP=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+CONFIG_NETFILTER_XT_MATCH_REALM=y
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=y
+# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_IP_SET=y
+CONFIG_IP_SET_MAX=256
+CONFIG_IP_SET_BITMAP_IP=y
+CONFIG_IP_SET_BITMAP_IPMAC=y
+CONFIG_IP_SET_BITMAP_PORT=y
+CONFIG_IP_SET_HASH_IP=y
+# CONFIG_IP_SET_HASH_IPMARK is not set
+CONFIG_IP_SET_HASH_IPPORT=y
+CONFIG_IP_SET_HASH_IPPORTIP=y
+CONFIG_IP_SET_HASH_IPPORTNET=y
+# CONFIG_IP_SET_HASH_NETPORTNET is not set
+CONFIG_IP_SET_HASH_NET=y
+# CONFIG_IP_SET_HASH_NETNET is not set
+CONFIG_IP_SET_HASH_NETPORT=y
+# CONFIG_IP_SET_HASH_NETIFACE is not set
+CONFIG_IP_SET_LIST_SET=y
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_NF_NAT_IPV4=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_CLUSTERIP=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_EUI64=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+# CONFIG_IP6_NF_MATCH_RPFILTER is not set
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_TARGET_HL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+# CONFIG_IP6_NF_TARGET_SYNPROXY is not set
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_NF_NAT_IPV6=y
+CONFIG_IP6_NF_TARGET_MASQUERADE=y
+CONFIG_IP6_NF_TARGET_NPT=y
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_L2TP=y
+# CONFIG_L2TP_V3 is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+CONFIG_FW_LOADER_USER_HELPER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_BLK_DEV_SKD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=y
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_BLK_DEV_RSXX is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ATMEL_SSC is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_PCH_PHUB is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_VMWARE_VMCI is not set
+
+#
+# Intel MIC Host Driver
+#
+# CONFIG_INTEL_MIC_HOST is not set
+
+#
+# Intel MIC Card Driver
+#
+# CONFIG_INTEL_MIC_CARD is not set
+# CONFIG_GENWQE is not set
+# CONFIG_ECHO is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# CONFIG_I2O is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+CONFIG_DUMMY=y
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=y
+# CONFIG_VETH is not set
+CONFIG_VIRTIO_NET=y
+# CONFIG_NLMON is not set
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+# CONFIG_VHOST_NET is not set
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_VORTEX is not set
+# CONFIG_TYPHOON is not set
+CONFIG_NET_VENDOR_ADAPTEC=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_NET_VENDOR_ALTEON=y
+# CONFIG_ACENIC is not set
+# CONFIG_ALTERA_TSE is not set
+CONFIG_NET_VENDOR_AMD=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_PCNET32 is not set
+# CONFIG_NET_VENDOR_ARC is not set
+CONFIG_NET_VENDOR_ATHEROS=y
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ALX is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2X is not set
+CONFIG_NET_VENDOR_BROCADE=y
+# CONFIG_BNA is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_CHELSIO_T4VF is not set
+CONFIG_NET_VENDOR_CISCO=y
+# CONFIG_ENIC is not set
+# CONFIG_CX_ECAT is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_DEC=y
+# CONFIG_NET_TULIP is not set
+CONFIG_NET_VENDOR_DLINK=y
+# CONFIG_DL2K is not set
+# CONFIG_SUNDANCE is not set
+CONFIG_NET_VENDOR_EMULEX=y
+# CONFIG_BE2NET is not set
+CONFIG_NET_VENDOR_EXAR=y
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+CONFIG_NET_VENDOR_HP=y
+# CONFIG_HP100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
+# CONFIG_I40E is not set
+# CONFIG_I40EVF is not set
+CONFIG_NET_VENDOR_I825XX=y
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+CONFIG_NET_VENDOR_MELLANOX=y
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_MLX5_CORE is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSZ884X_PCI is not set
+CONFIG_NET_VENDOR_MYRI=y
+# CONFIG_MYRI10GE is not set
+# CONFIG_FEALNX is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+# CONFIG_NATSEMI is not set
+# CONFIG_NS83820 is not set
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_NE2K_PCI is not set
+CONFIG_NET_VENDOR_NVIDIA=y
+# CONFIG_FORCEDETH is not set
+CONFIG_NET_VENDOR_OKI=y
+# CONFIG_PCH_GBE is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_PACKET_ENGINE=y
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_NET_VENDOR_QLOGIC=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_QLGE is not set
+# CONFIG_NETXEN_NIC is not set
+CONFIG_NET_VENDOR_REALTEK=y
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R8169 is not set
+# CONFIG_SH_ETH is not set
+CONFIG_NET_VENDOR_RDC=y
+# CONFIG_R6040 is not set
+CONFIG_NET_VENDOR_SAMSUNG=y
+# CONFIG_SXGBE_ETH is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SILAN=y
+# CONFIG_SC92031 is not set
+CONFIG_NET_VENDOR_SIS=y
+# CONFIG_SIS900 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SFC is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_SMSC9420 is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_SUN=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NIU is not set
+CONFIG_NET_VENDOR_TEHUTI=y
+# CONFIG_TEHUTI is not set
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TLAN is not set
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_WLAN=y
+# CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_WL_TI is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+CONFIG_FIX_EARLYCON_MEM=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MFD_HSU is not set
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_RP2 is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+# CONFIG_PTP_1588_CLOCK_PCH is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_K10TEMP is not set
+# CONFIG_SENSORS_FAM15H_POWER is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_CORETEMP is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+
+#
+# ACPI drivers
+#
+# CONFIG_SENSORS_ACPI_POWER is not set
+# CONFIG_SENSORS_ATK0110 is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_GOV_STEP_WISE=y
+# CONFIG_THERMAL_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_EMULATION is not set
+# CONFIG_INTEL_POWERCLAMP is not set
+# CONFIG_ACPI_INT3403_THERMAL is not set
+
+#
+# Texas Instruments thermal drivers
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_CS5535 is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RTSX_PCI is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+# CONFIG_VGA_SWITCHEROO is not set
+
+#
+# Direct Rendering Manager
+#
+# CONFIG_DRM is not set
+
+#
+# Frame buffer Devices
+#
+# CONFIG_FB is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+# CONFIG_SND is not set
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=y
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO_TPKBD is not set
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_SAMSUNG_USB2PHY is not set
+# CONFIG_SAMSUNG_USB3PHY is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+CONFIG_VIRTIO=y
+
+#
+# Virtio drivers
+#
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+# CONFIG_ACERHDF is not set
+# CONFIG_ASUS_LAPTOP is not set
+# CONFIG_FUJITSU_TABLET is not set
+# CONFIG_HP_ACCEL is not set
+# CONFIG_HP_WIRELESS is not set
+# CONFIG_THINKPAD_ACPI is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_INTEL_MENLOW is not set
+# CONFIG_ACPI_WMI is not set
+# CONFIG_TOPSTAR_LAPTOP is not set
+# CONFIG_TOSHIBA_BT_RFKILL is not set
+# CONFIG_ACPI_CMPC is not set
+# CONFIG_INTEL_IPS is not set
+# CONFIG_IBM_RTL is not set
+# CONFIG_XO15_EBOOK is not set
+# CONFIG_SAMSUNG_Q10 is not set
+# CONFIG_INTEL_RST is not set
+# CONFIG_INTEL_SMARTCONNECT is not set
+# CONFIG_PVPANIC is not set
+# CONFIG_CHROME_PLATFORMS is not set
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_CLKEVT_I8253=y
+CONFIG_I8253_LOCK=y
+CONFIG_CLKBLD_I8253=y
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+CONFIG_IOMMU_SUPPORT=y
+# CONFIG_AMD_IOMMU is not set
+# CONFIG_INTEL_IOMMU is not set
+# CONFIG_IRQ_REMAP is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_NTB is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_PWM is not set
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+CONFIG_DMIID=y
+# CONFIG_DMI_SYSFS is not set
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=y
+CONFIG_9P_FS_POSIX_ACL=y
+# CONFIG_9P_FS_SECURITY is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_FENTRY=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_UPROBE_EVENT is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_MMIOTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+# CONFIG_X86_PTDUMP is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_DEBUG_RODATA_TEST=y
+CONFIG_DOUBLEFAULT=y
+# CONFIG_DEBUG_TLBFLUSH is not set
+# CONFIG_IOMMU_DEBUG is not set
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_OPTIMIZE_INLINING is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+# CONFIG_X86_DEBUG_STATIC_CPU_HAS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_ABLK_HELPER=y
+CONFIG_CRYPTO_GLUE_HELPER_X86=y
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_SEQIV=y
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=y
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_XTS=y
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRC32_PCLMUL is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+CONFIG_CRYPTO_GHASH=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=y
+CONFIG_CRYPTO_RMD160=y
+CONFIG_CRYPTO_RMD256=y
+CONFIG_CRYPTO_RMD320=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA1_SSSE3 is not set
+CONFIG_CRYPTO_SHA256_SSSE3=y
+CONFIG_CRYPTO_SHA512_SSSE3=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_X86_64=y
+CONFIG_CRYPTO_AES_NI_INTEL=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_BLOWFISH_COMMON=y
+CONFIG_CRYPTO_BLOWFISH_X86_64=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_CAMELLIA_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=y
+CONFIG_CRYPTO_CAST_COMMON=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST5_AVX_X86_64=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_CAST6_AVX_X86_64=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_SALSA20=y
+CONFIG_CRYPTO_SALSA20_X86_64=y
+CONFIG_CRYPTO_SEED=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_SERPENT_SSE2_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX2_X86_64=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+CONFIG_CRYPTO_TWOFISH_X86_64=y
+CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=y
+CONFIG_CRYPTO_TWOFISH_AVX_X86_64=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZ4=y
+CONFIG_CRYPTO_LZ4HC=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_USER_API=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4HC_COMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
diff --git a/testing/do-tests b/testing/do-tests
index becb7f1..35f13ec 100755
--- a/testing/do-tests
+++ b/testing/do-tests
@@ -491,20 +491,47 @@ do
 	do
 	    eval HOSTLOGIN=root@\$ipv4_${host}
 
-	    for command in statusall listall
-	    do
-		ssh $SSHCONF $HOSTLOGIN ipsec $command \
-		    > $TESTRESULTDIR/${host}.$command 2>/dev/null
-	    done
+		scp $SSHCONF $HOSTLOGIN:/etc/strongswan.conf \
+		    $TESTRESULTDIR/${host}.strongswan.conf  > /dev/null 2>&1
 
-	    for file in strongswan.conf ipsec.conf ipsec.secrets
-	    do
-		scp $SSHCONF $HOSTLOGIN:/etc/$file \
-		    $TESTRESULTDIR/${host}.$file  > /dev/null 2>&1
-	    done
+		if [ $SUBDIR = "swanctl" ]
+		then
+			scp $SSHCONF $HOSTLOGIN:/etc/swanctl/swanctl.conf \
+			$TESTRESULTDIR/${host}.swanctl.conf  > /dev/null 2>&1
+
+		    ssh $SSHCONF $HOSTLOGIN swanctl --list-conns \
+			    > $TESTRESULTDIR/${host}.swanctl.conns 2>/dev/null
+
+		    ssh $SSHCONF $HOSTLOGIN swanctl --list-certs \
+			    > $TESTRESULTDIR/${host}.swanctl.certs 2>/dev/null
+
+		    ssh $SSHCONF $HOSTLOGIN swanctl --list-pools \
+			    > $TESTRESULTDIR/${host}.swanctl.pools 2>/dev/null
+
+		    ssh $SSHCONF $HOSTLOGIN swanctl --list-sas \
+			    > $TESTRESULTDIR/${host}.swanctl.sas 2>/dev/null
 
-	    scp $SSHCONF $HOSTLOGIN:/etc/ipsec.d/ipsec.sql \
-		$TESTRESULTDIR/${host}.ipsec.sql  > /dev/null 2>&1
+		    ssh $SSHCONF $HOSTLOGIN swanctl --list-pols \
+			    > $TESTRESULTDIR/${host}.swanctl.pols 2>/dev/null
+
+		    ssh $SSHCONF $HOSTLOGIN swanctl --stats \
+			    > $TESTRESULTDIR/${host}.swanctl.stats 2>/dev/null
+		else
+		    for file in ipsec.conf ipsec.secrets
+		    do
+				scp $SSHCONF $HOSTLOGIN:/etc/$file \
+			    $TESTRESULTDIR/${host}.$file  > /dev/null 2>&1
+		    done
+
+		    for command in statusall listall
+		    do
+				ssh $SSHCONF $HOSTLOGIN ipsec $command \
+			    > $TESTRESULTDIR/${host}.$command 2>/dev/null
+		    done
+
+		    scp $SSHCONF $HOSTLOGIN:/etc/ipsec.d/ipsec.sql \
+			$TESTRESULTDIR/${host}.ipsec.sql  > /dev/null 2>&1
+		fi
 
 	    ssh $SSHCONF $HOSTLOGIN ip -s xfrm policy \
 		    > $TESTRESULTDIR/${host}.ip.policy 2>/dev/null
@@ -515,7 +542,46 @@ do
 	    ssh $SSHCONF $HOSTLOGIN $IPTABLES_CMD \
 		    > $TESTRESULTDIR/${host}.iptables 2>/dev/null
 	    chmod a+r $TESTRESULTDIR/*
-	    cat >> $TESTRESULTDIR/index.html <<@EOF
+
+		if [ $SUBDIR = "swanctl" ]
+		then
+		    cat >> $TESTRESULTDIR/index.html <<@EOF
+    <h3>$host</h3>
+      <table border="0" cellspacing="0" width="600">
+      <tr>
+	<td valign="top">
+	  <ul>
+	    <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>
+	  </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.stats">swanctl --stats</a></li>
+	    <li><a href="$host.auth.log">auth.log</a></li>
+	    <li><a href="$host.daemon.log">daemon.log</a></li>
+	  </ul>
+      </td>
+	<td valign="top">
+	  <ul>
+	    <li><a href="$host.ip.policy">ip -s xfrm policy</a></li>
+	    <li><a href="$host.ip.state">ip -s xfrm state</a></li>
+	    <li><a href="$host.ip.route">$IPROUTE_DSP</a></li>
+	    <li><a href="$host.iptables">$IPTABLES_DSP</a></li>
+	  </ul>
+	   
+      </td>
+    </tr>
+    </table>
+ at EOF
+
+		else
+		    cat >> $TESTRESULTDIR/index.html <<@EOF
     <h3>$host</h3>
       <table border="0" cellspacing="0" width="600">
       <tr>
@@ -546,7 +612,7 @@ do
     </tr>
     </table>
 @EOF
-
+		fi
 	done
 
 	for host in $RADIUSHOSTS
@@ -653,7 +719,7 @@ do
 	for host in $IPSECHOSTS
 	do
 	    eval HOSTLOGIN=root@\$ipv4_${host}
-	    ssh $SSHCONF $HOSTLOGIN "grep -E 'charon|last message repeated|imcv' \
+	    ssh $SSHCONF $HOSTLOGIN "grep -E 'charon|last message repeated|imcv|pt-tls-client' \
 		/var/log/auth.log" >> $TESTRESULTDIR/${host}.auth.log
 	done
 
diff --git a/testing/hosts/alice/etc/swanctl/rsa/aliceKey.pem b/testing/hosts/alice/etc/swanctl/rsa/aliceKey.pem
new file mode 100644
index 0000000..51f9c0d
--- /dev/null
+++ b/testing/hosts/alice/etc/swanctl/rsa/aliceKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA2I1qSBHmly3Q2qKt88kRv17dhmRge+pn9FQnoRr1kYTwq5DE
+YAe4tapp//casv8tgizV9MnslM0y749J5zyR/0jkDEi0/Nv65LAj2FdDGGU0nxX5
+mOz1DcZf/n3BLcNwcXiLxvzwj9/tosbAc6hHJP9Rk9c8YisdL1RaH/nT/9D8Yut6
+K+hbrkJ+Pug2LfAxNjBkHkzI9jmr0xFxjIQ9rQY0zQbPNh8gSRDPye5Iv+pZCuYu
+aVLoq3DkvcdexRoqKca3TEjuMsZaHjKyeuMw3ErNG3YshOpI+2hNNHYkHprn/rnj
+iYHYUYSulJ38uAZObDM6CWhkumxCCw3rGOlS+wIDAQABAoIBAFh3/ZGP7pqYlxib
+GWHdJSj/gpTi8R/utaV1s/L3ZpearhAJRpDM1sMw6bkupHO4GEl0M7ybudFYu5Ru
+/4w+jI60oqX6FiavYCKJazt4+uo+fm73tU6qj7qe7pyzl3YwwAE7dC9JKqY8n4K+
+m+UkPFx7CkLRzdN1NakeVut1TwzU/cUtAV8iY1yEtw/KyiyL/I7aJ3zZ1pg+5kRS
+JLKDrRlf0xQ+I7AY12XrSimbLqxmyVmWq74Fm/YAWGgvi/Nx04Zg/C4wp4A+izFt
+N8zWjktY1brRrCnRfUEcevv5hPqFxfOPFmB9x7mX/8eH5v2T+XR9swoF92xWHxQ5
+7tcB4NECgYEA69dBy4God5TW1FyT7DbgKHd7BVtOVLjsbQxc8UNBN/mHemUGMs1v
+lemW0ZPddU2/rqd3jlZuP4zv/6D9OZ0omi8auejO2WwAbut6JBX+dlvF9+owyU3h
+CraycFaxZIMn+JzXbIunmVUrVE1QvpBFaNXlC47cO8CmQlMV0nChzZ8CgYEA6xAV
+F1L0iqISsCu0q1iM4LtHVT944o815B8RlREOPxROXJaJQ8phVQgT5PXRkHZDn55Z
+mKqkAX2KwjBQj0KfUvmJ6D8T6OZOe08/oSwiBrBpSQsH3AA7mmDXyT3gRsma0jnj
+cNGjecG9VXbJiZnBetGdLuvSnVYfdkcw4atthSUCgYEAhaFMaJEo8cjmCSIDtt5J
+GOTKUfiwY5T8cbWFnDatZ5f9yb4gSvzYcysOB+Yun17Uc5P0TDRw95VWD5Qap2CD
+NwnlrN1bBxsJC9BlPrkvm8TYYWbTCd0U3Es0xC57CSa/qUDFV32yE1GM4ZGFZNS+
+X26C/4+M/lZkXkRRoxGqvKUCgYEAugOyDRESf5qeG1ea03Vxlm3dlzJxYShfRzTm
+3wXuNjDFijN+UG0Y9Qc9ZxS4UA+ml+vhjxSKULueUOmW9qeMGUdrwKQaB1YpiR8/
+hTW9f3me97SI9aohgJteZ9xVXO8xW2d/+smLClEsmTM1bXSFTcIPFxB7TRLYNutD
+XXIhaxkCgYBEQECMTKNZcGf67fjmA6PMpMGlwbVGmyXYYK4I+IRNUFWyrpNalmr/
+LXj7m1EYcx4BK7BrpDUgnm8q37BAwYOioLJFWLK58iW1B+Qvg6jlwnr+ZaYhZx94
+D/SL9GuQQTQtxlFex4Wale7R8xNdt7xuVJD6pE3mFVkXN4+OrI+EWQ==
+-----END RSA PRIVATE KEY-----
diff --git a/testing/hosts/alice/etc/swanctl/x509/aliceCert.pem b/testing/hosts/alice/etc/swanctl/x509/aliceCert.pem
new file mode 100644
index 0000000..49fe4b8
--- /dev/null
+++ b/testing/hosts/alice/etc/swanctl/x509/aliceCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEHzCCAwegAwIBAgIBGTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTA5MDgyNzEwMDcyNFoXDTE0MDgyNjEwMDcyNFowVzELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xDjAMBgNVBAsTBVNhbGVz
+MR0wGwYDVQQDFBRhbGljZUBzdHJvbmdzd2FuLm9yZzCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANiNakgR5pct0NqirfPJEb9e3YZkYHvqZ/RUJ6Ea9ZGE
+8KuQxGAHuLWqaf/3GrL/LYIs1fTJ7JTNMu+PSec8kf9I5AxItPzb+uSwI9hXQxhl
+NJ8V+Zjs9Q3GX/59wS3DcHF4i8b88I/f7aLGwHOoRyT/UZPXPGIrHS9UWh/50//Q
+/GLreivoW65Cfj7oNi3wMTYwZB5MyPY5q9MRcYyEPa0GNM0GzzYfIEkQz8nuSL/q
+WQrmLmlS6Ktw5L3HXsUaKinGt0xI7jLGWh4ysnrjMNxKzRt2LITqSPtoTTR2JB6a
+5/6544mB2FGErpSd/LgGTmwzOgloZLpsQgsN6xjpUvsCAwEAAaOCAQYwggECMAkG
+A1UdEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdDgQWBBQF2gQgjAL0KEcKz2x3LQZm
+E9qGPDBtBgNVHSMEZjBkgBRdp91wBlEyfue2bbO15eBg6i5N76FJpEcwRTELMAkG
+A1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0
+cm9uZ1N3YW4gUm9vdCBDQYIBADAfBgNVHREEGDAWgRRhbGljZUBzdHJvbmdzd2Fu
+Lm9yZzA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4ub3Jn
+L3N0cm9uZ3N3YW4uY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQBWv4PhHGVpiLF5M3Rn
+qQLSoRFjKqn3N9We81RWwVRpBzwoUEaHizelaVct9FJg6t7Fk/D8F0wag5EFKlcg
+KQ8fd/0qLE393uwGb4Dvql2w49NFFDUsk5FC+pMUDAYsWHyFu26WKY5kfaMwNMNJ
+HK6e4m6+Wmoy5ulkatwDJRDqkyG11YJ/p0n0HAG1DBJoL9079U+xQxT+9a2f7TaO
+B/UbQNOvOgqaddk5uUDTjqnY/bltbAAuuI1ZNMrPCCNUorcdhySJb1tlF/JXTTB6
+N60XqYRYnk5T1yftNU0AA26ggskv4MMDwgYCGsyZuCX9vW+XsArRQJ5fsSZDiO7R
+8FT2
+-----END CERTIFICATE-----
diff --git a/testing/hosts/alice/etc/swanctl/x509ca/strongswanCert.pem b/testing/hosts/alice/etc/swanctl/x509ca/strongswanCert.pem
new file mode 100644
index 0000000..0865ad2
--- /dev/null
+++ b/testing/hosts/alice/etc/swanctl/x509ca/strongswanCert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+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=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/bob/etc/swanctl/rsa/bobKey.pem b/testing/hosts/bob/etc/swanctl/rsa/bobKey.pem
new file mode 100644
index 0000000..e74392b
--- /dev/null
+++ b/testing/hosts/bob/etc/swanctl/rsa/bobKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA18MU7aM5sSmlIQtE+R78VUoXzOY0ECsCM0lQGXl1KQYENri0
+/R5/ye26GlCBNV39dcwkSJXMuV5LqYWtoH6hJkW3n2ADq/zRbguKTxA3iY1oP5og
+maPfwx9olrwr1OBgnK2Pyyg3g6Ci/X3PR+RU7QP2NboG6KDjtcqFdOHqLTJr5mHK
+lLQl/ofzn/cTNMNJumqAyFwIY3ChDzIP1i+WnFrlVWljjWvsex6EFA3vvTIKAdVZ
+mqAe+1WGiu9owYW76JxfBoxG90YrpH7jCDpOcjfTh8wPTgyW0w70ppkJLYf6BBwC
+/7czkNs4xKbbCr8Kv93axm3URDv3Kd/SOf2URQIDAQABAoIBAQC/GZwptk5c6ePF
+1rNqatVXvV5DLwmh4FX8ksyNI5Rvl1KYHRTAtAi/Ev2oXPF0ESFy+jKQz40aCbi+
+FxZndoDI4yr10BaweCYOb846pMRr4oEZBCwnqIuByQnbqCKyU2F+pAMeDyrMPLTg
+DFRQ+p11p/KkN3XzCL1mwE9f7NB64fIwIaoAPb5EzELq3SXbBn1MCDPcvZEeyqUW
+jW9OGe2hmen7Vk7JLE+2XU6Wyo6X4RWkj2lpOxofuxff4pI+xoiWmZxV93FzZoCo
+R55TP0AtgyRUQyRrSgSV8T34sZI79ZBt1N6JBdnOl8sl4niQu5laBKJGKWnEiiPE
+w7vUmHLBAoGBAP45AScORw0eb8K4Xy1UAaWZnSzN4z35QxkjelQ05Hkd9lrpwRBz
+Us2Yo35spvaI+/sYmnYC6vdnFRTdhVfHY4uTyODWOawhMM1mnWoRo0MohCyBBOjZ
+XGeOROWV4uGld6dLj4zoKfDWyw2y9ChT8kxidSmJajxese6DovTv1ov5AoGBANlF
+PgRyOCUZK5I1XTzkbt4GMUrRh3gAnTM84enjJHtxo+IZuwhVA8wgfl6k+LXAP49k
+si3HnmsAAezqFJOapbBf9zZSCTPTYDFk9qyu8TXw32K48obhb3Ns80Ba4sqVCixo
+K3NpOE5OaNxEdBHmi39RJf1fyUNZ+u+cz4xXdiWtAoGAChXo3cvLNdIHTQpTfFDg
+39kAS06/vS2uY8jsiXqvtb5ij6jGaAirOEzd754P4af9lzCasCPdfoMwaut+5sSa
+RmdOiNz23MVUUlHH3PVmLLvmwn073KEC8XjLcvBHV/xgitqMj2KGh29+DsUSuqbZ
+7f3Z+BPjixGWrYe7Z0w8jsECgYEA1a/MNwM/RP1kZQAnG2Rvxd3BTRyWZ+fytBoE
+9st3bhFuZUl5MdCrU3AB2YPXOKpD2PvoYi4aGJKBUklGw4UtwDIiKUK12kriKLJs
+CZplke+9RJMxtIaz3oohFAJPW38J6nLpiTDLN/jWGQ0aOyDLwgRFoNU8VQmCS3em
+iRjcEmECgYEAgyrUsD+qScWzS3GvkZITcy20+iCVfxXH8ZznNVHGFoFZ+3uu/kH+
+u0yXPXPux2t5P2+Ybm4ojV09/QWaJgHVoL7PBiyk5AhXO0A1EK0NG8uJeYaMthJk
+D6RrYXqdmKrSEDTh2DvE6W149sRgO2Z3b0FGgzjYjhSFF/ePZxAFiIQ=
+-----END RSA PRIVATE KEY-----
diff --git a/testing/hosts/bob/etc/swanctl/x509/bobCert.pem b/testing/hosts/bob/etc/swanctl/x509/bobCert.pem
new file mode 100644
index 0000000..00ecd5a
--- /dev/null
+++ b/testing/hosts/bob/etc/swanctl/x509/bobCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBGjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTA5MDgyNzEwMDgxOFoXDTE0MDgyNjEwMDgxOFowWDELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAPBgNVBAsTCFJlc2Vh
+cmNoMRswGQYDVQQDFBJib2JAc3Ryb25nc3dhbi5vcmcwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDXwxTtozmxKaUhC0T5HvxVShfM5jQQKwIzSVAZeXUp
+BgQ2uLT9Hn/J7boaUIE1Xf11zCRIlcy5Xkupha2gfqEmRbefYAOr/NFuC4pPEDeJ
+jWg/miCZo9/DH2iWvCvU4GCcrY/LKDeDoKL9fc9H5FTtA/Y1ugbooOO1yoV04eot
+MmvmYcqUtCX+h/Of9xM0w0m6aoDIXAhjcKEPMg/WL5acWuVVaWONa+x7HoQUDe+9
+MgoB1VmaoB77VYaK72jBhbvonF8GjEb3RiukfuMIOk5yN9OHzA9ODJbTDvSmmQkt
+h/oEHAL/tzOQ2zjEptsKvwq/3drGbdREO/cp39I5/ZRFAgMBAAGjggEEMIIBADAJ
+BgNVHRMEAjAAMAsGA1UdDwQEAwIDqDAdBgNVHQ4EFgQUYUK/uIcou7BS8ODHk9Ro
+PGJP1FcwbQYDVR0jBGYwZIAUXafdcAZRMn7ntm2zteXgYOouTe+hSaRHMEUxCzAJ
+BgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRswGQYDVQQDExJz
+dHJvbmdTd2FuIFJvb3QgQ0GCAQAwHQYDVR0RBBYwFIESYm9iQHN0cm9uZ3N3YW4u
+b3JnMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwuc3Ryb25nc3dhbi5vcmcv
+c3Ryb25nc3dhbi5jcmwwDQYJKoZIhvcNAQELBQADggEBAEIkmrK7GPm4H/FAEVCN
+775XpuofsfGjT/bO/aPCqb+uPwwcKeUfxzICQDEqMv+mtxGuLjtfmTWwUcoPMgN+
+2HZDJGa1+kK2VLUz3QBIQXSdusbITb0ND/xCvbGwsk9y/0DGBnAo3xNBNM73ZQ8k
+/A7mQ2nnQfzI9gQ342FOuTTb/kwrVNixQI3dhvf6Th5Dj5rZfQs6c09+9jRLGBFx
+g7qQ1gej0fi6XYX4cSNwluu/Vo6xT5epEeTU5KoYn0mtOqFx6AY8xzIqQLvY4m8g
+viGoGRqId1gqNiEfshb8KICPI29WyiBRzMKO6reeb+446A9CSLgMW0Ze3SCRXrjr
+2nQ=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/bob/etc/swanctl/x509ca/strongswanCert.pem b/testing/hosts/bob/etc/swanctl/x509ca/strongswanCert.pem
new file mode 100644
index 0000000..0865ad2
--- /dev/null
+++ b/testing/hosts/bob/etc/swanctl/x509ca/strongswanCert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+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=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/carol/etc/swanctl/rsa/carolKey.pem b/testing/hosts/carol/etc/swanctl/rsa/carolKey.pem
new file mode 100644
index 0000000..ce17e71
--- /dev/null
+++ b/testing/hosts/carol/etc/swanctl/rsa/carolKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA0F1ZT4EXvHiXKj7EeevhQA5Tz3JBC5Pm90+hfPHqRE+yNgC6
+6S2BdH5JouRAfD9hGAM9IqPmfOaaU5B/+tZGv7w7ar4L3ZpQgKaQ29kZqajnDZaU
+4xnpPl2TYe/5AzrFP8bNbJWvV0xi7/u3LAPUHDtpb8eqRERIO7qr3lVa74vODpeX
+EI0R7PRixms398LoEvarMoCowFsgcVbw46eH6cRjggXkDORmcWvDXYYjvZnzzanD
+3uXIrBmFLP8YxAUEnH6uc13Dk/UgnBOUbk9R2gMK178xyvWKID7M6i/HnnHUagbF
+26hdZTl6Ct/Uy1qVF/09zxevirdYQpMCaxmtUQIDAQABAoIBAQCKhvVgoS/Zssa1
+ZGOVt1fbEWtxCMHr45nzpDJ18hPQ9LdDpfqeGg3uGCP2sw+YSz7PCyAzDoqnUV0a
+33/mkV0aDhfmoJEc9II+9f5q24xvOobahtlXnxttxiK9QyDnn8QR4acjYOThAjzo
+1g3yqlzzpCA2G6W8mzT22OV4/IBnrvRX/ypakffHyKTyQsxGqxz/GNbRpNi4K1eR
+3x8YoEuMstojXDp5WQD6f/u8tLHQeaUEZzeU7spedcjBatJViWVFNRX1cYC43FGH
+EKqHTNO83t3xCdW1U8J6NRQ3+cG834lA8/+GMt1Z9sjgEQe0u/ScbFQJtunssp6t
+ozOAD6XRAoGBAPVTcEXQZ99NeG32fhz+oBzjym3j8Gvkjv2LTcSMHsGacRADh17i
+AjQ8hRyPlw0hYKLk0RCNpkN69rzProA/YfxFBYKomqCQbLpl/HAzqlhMGioX6Wsv
+NolRrtqlJh9uHBSZnPp/TECRiQ7/KBy05vNyCfS21XeGB8rsoKFRN3RtAoGBANlu
+N5ultO1gTYSn7XFnih8jORt0mmlyib077l0XmFr4kmT17DXT43seRNb9r+yKeK4Z
+ngu2gPWfmAC7iUulsx7pZPPdwULzYYNc9Joe23UzD0TzPCbFbgdSrj/g33YIOLZD
+e5mhMctUTWTamWuvO8P1cJzHXxNLBIzeu/i+0aX1AoGAF+LY4qNJCc/0Mti2LMKJ
++mYfdpWj+g1V8s/WcZWnBPixm3qMequMxWNDHqXIcknWq+WViYQRNS7KyVV7Sxdg
+xfw+bhtWet21CG0XqCEPq+s0/PY5DuuY5sPiP32m+ZZx+3t9clJkrUC+VIx5bloa
+xodK+t22aR3Osm5ZsXtD5/0CgYEArJDLVZ8In7VlELnuu6i/eMMN2fqLatFa/HOK
+VRwa8WiDV9nOpVIMI3T8kd06OPQVn6f5RbaNV2RY0YwGBaH3LbtzQhFoB2j+pbGq
++H8xEi16GvEpdmQPVYSLg2tIL3eK+y1H9cB3sravzjGovkyPlJFB1Uxu6vMJI3zL
+lzprTdkCgYAl7EF4x/fAF8Rqk/vbcuLjsZmuM8n6aDT4G3W0gc1nVhJMdEyCGxJr
+B+qYUtxY3kDMh/FgIJ2K87S6xIYneNPiHL/fzbv6rYkRUA9DpDBBuI7vsnxmrf/+
+ucit2V0aTtBfC9gaTtp5/UoIhaSjutDc3ez4NAHBnfch1sxxY8QSXg==
+-----END RSA PRIVATE KEY-----
diff --git a/testing/hosts/carol/etc/swanctl/x509/carolCert.pem b/testing/hosts/carol/etc/swanctl/x509/carolCert.pem
new file mode 100644
index 0000000..6c41df9
--- /dev/null
+++ b/testing/hosts/carol/etc/swanctl/x509/carolCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEIjCCAwqgAwIBAgIBHTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTA5MDgyNzEwNDQ1MVoXDTE0MDgyNjEwNDQ1MVowWjELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAPBgNVBAsTCFJlc2Vh
+cmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZzCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBANBdWU+BF7x4lyo+xHnr4UAOU89yQQuT5vdPoXzx
+6kRPsjYAuuktgXR+SaLkQHw/YRgDPSKj5nzmmlOQf/rWRr+8O2q+C92aUICmkNvZ
+Gamo5w2WlOMZ6T5dk2Hv+QM6xT/GzWyVr1dMYu/7tywD1Bw7aW/HqkRESDu6q95V
+Wu+Lzg6XlxCNEez0YsZrN/fC6BL2qzKAqMBbIHFW8OOnh+nEY4IF5AzkZnFrw12G
+I72Z882pw97lyKwZhSz/GMQFBJx+rnNdw5P1IJwTlG5PUdoDCte/Mcr1iiA+zOov
+x55x1GoGxduoXWU5egrf1MtalRf9Pc8Xr4q3WEKTAmsZrVECAwEAAaOCAQYwggEC
+MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdDgQWBBQfoamI2WSMtaCiVGQ5
+tPI9dF1ufDBtBgNVHSMEZjBkgBRdp91wBlEyfue2bbO15eBg6i5N76FJpEcwRTEL
+MAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMT
+EnN0cm9uZ1N3YW4gUm9vdCBDQYIBADAfBgNVHREEGDAWgRRjYXJvbEBzdHJvbmdz
+d2FuLm9yZzA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4u
+b3JnL3N0cm9uZ3N3YW4uY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQC8pqX3KrSzKeul
+GdzydAV4hGwYB3WiB02oJ2nh5MJBu7J0Kn4IVkvLUHSSZhSRxx55tQZfdYqtXVS7
+ZuyG+6rV7sb595SIRwfkLAdjbvv0yZIl4xx8j50K3yMR+9aXW1NSGPEkb8BjBUMr
+F2kjGTOqomo8OIzyI369z9kJrtEhnS37nHcdpewZC1wHcWfJ6wd9wxmz2dVXmgVQ
+L2BjXd/BcpLFaIC4h7jMXQ5FURjnU7K9xSa4T8PpR6FrQhOcIYBXAp94GiM8JqmK
+ZBGUpeP+3cy4i3DV18Kyr64Q4XZlzhZClNE43sgMqiX88dc3znpDzT7T51j+d+9k
+Rf5Z0GOR
+-----END CERTIFICATE-----
diff --git a/testing/hosts/carol/etc/swanctl/x509ca/strongswanCert.pem b/testing/hosts/carol/etc/swanctl/x509ca/strongswanCert.pem
new file mode 100644
index 0000000..0865ad2
--- /dev/null
+++ b/testing/hosts/carol/etc/swanctl/x509ca/strongswanCert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+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=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/dave/etc/swanctl/rsa/daveKey.pem b/testing/hosts/dave/etc/swanctl/rsa/daveKey.pem
new file mode 100644
index 0000000..c0a5b42
--- /dev/null
+++ b/testing/hosts/dave/etc/swanctl/rsa/daveKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAwAfyU28FWOaDRdPvAXoXW3NDTnl/m5dEjnIKWYWup2zAUDuN
+Y7TiOa+V24PbCvZfg2Dp2UGRLBISFWQ6CvMhiPxSBBPoFkX/ji5iPJNivhtXZJUw
+v1T9rWVjEGEFrOlJ194olaR3HCNwkKqiVnvX2bCLKtCfY/YbuofXRiBG6J+kVwyz
+yOQyIiCnN69IwxzQ7CFA83I7lHQsShQjLh1An2tTwYqqY+aT+l09BoCOlI24JzVj
+0z29msROz9ceYEJlcIhYmLPlU4dn6vTvcTcZ5/2Jsy5OP2DZcu8WF0N9TboUr0aR
++47CdaeFUrrp2Kr3HD1CrKeT7wrQnhrzU9qrdQIDAQABAoIBAQCB4t4dYPKU9xXD
+nV4D+bjiukvEQJn3e5F7Z9doReukgwJxQlaYIjkCG6mZGM6H0603B84kjRzMWkyw
++2HnFhyQs1omN/C7YA1C9kyr/GTFgWjTN7YJNEuBhRpEcduM4R55TGLXFK8b8Tyq
+HUBAjvOo4qi/BO1Kh6Spvkf1vs83d9clTParD/Tz4QkjUzR5awMKHgOVGgrmTiJL
+Miao6ZF0gl6qh377xc3gzQdWh6kIb2RWVL2lR/iSdDP47s2ez8ubMO1v9mu05bc0
+H5YmCVeY4nkzjlVARdCuPulKHxBkStiPEOfnGZkj1F1fjfIoOFnD9MQSYkJuZUoE
+6JWiG7QBAoGBAOouYy7W0xRlXGTrahjU9JL+o3nKCRQmvX84Hxy9fx95tz1pS5U4
+7Gk7JFmS9qKhspInnblpjqxA5D3zqoO2gspatg7QfQJpLhbGXLqR7pqp92jbK+mh
+4KITqTZRpohtzTWqPxFupzKHo5qDDMJ3m8ArnIVmxM+M0lzpn6Awq5ZVAoGBANHs
+NR2voz//E6ZMSpgKb2l3NecFwdwqQQtzghD0wFnNBYV55DJNRuW7DB5t9EdtGgAg
+b2bPG+I2RdsZPGnL0EU5+H4rP0YXBGAxoVdaFqjnG5mIRN8mAdnWeVhCH3XBmUP1
+OFe1aghYMyC0ioXe8Vt1yaxeSiMjY4JKtma2DKChAoGBAIedv4CDlg/Mt1oWXwXs
+ZYqu/nrsPp+1463GEXZyYykWMsDUtpm/MmGqh118V2pNW/16BcQ3VhF5LvSVpNzM
+GCgZqi8gHBUGVlOIInFFS7mzznyh2GdfgJg77JVxaZC+jcWTRxzQSPFhTaSQWhZQ
+cBk06Fr07esIMVbvUKrTJLtVAoGBAIFCMsqetaTYSZ8iZuQLuOJ19wjTsLUCh56n
+dzU9n5sr9PRlQ6/9iWQ3spSiG8JHWbUuQ6pIaOD3jjgE6AA08X9O3MXDl2hvD9Cz
+fqcs37sM4x+8mrvUyVr7ByjjPj/h/5+qxRCssieFN6YxxQH9bxxkANRUEs5kIge+
+PWYtPsVBAoGAVako4J2YAfaD67Yl5u2XOWrBzVWzWNeqBsiAF1nCpR1RfeH4jFN/
+Uy/qbPVjdm14GNwd5wtI0xwBAsrTVit78DoxC2MUKMIuq9xVVakKX8UxBmCnldkW
+uhtXwJWH9pfQncCSrEaecfDkL8YVPDX/4XeJjqHpKqbyjTuGv+MK1Yw=
+-----END RSA PRIVATE KEY-----
diff --git a/testing/hosts/dave/etc/swanctl/x509/daveCert.pem b/testing/hosts/dave/etc/swanctl/x509/daveCert.pem
new file mode 100644
index 0000000..f212e19
--- /dev/null
+++ b/testing/hosts/dave/etc/swanctl/x509/daveCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEIjCCAwqgAwIBAgIBHDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTA5MDgyNzEwMzczOVoXDTE0MDgyNjEwMzczOVowWzELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzARBgNVBAsTCkFjY291
+bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmcwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDAB/JTbwVY5oNF0+8Behdbc0NOeX+bl0SOcgpZ
+ha6nbMBQO41jtOI5r5Xbg9sK9l+DYOnZQZEsEhIVZDoK8yGI/FIEE+gWRf+OLmI8
+k2K+G1dklTC/VP2tZWMQYQWs6UnX3iiVpHccI3CQqqJWe9fZsIsq0J9j9hu6h9dG
+IEbon6RXDLPI5DIiIKc3r0jDHNDsIUDzcjuUdCxKFCMuHUCfa1PBiqpj5pP6XT0G
+gI6UjbgnNWPTPb2axE7P1x5gQmVwiFiYs+VTh2fq9O9xNxnn/YmzLk4/YNly7xYX
+Q31NuhSvRpH7jsJ1p4VSuunYqvccPUKsp5PvCtCeGvNT2qt1AgMBAAGjggEFMIIB
+ATAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDqDAdBgNVHQ4EFgQU7n842u6huBpBd394
+8mdL6EOdjg4wbQYDVR0jBGYwZIAUXafdcAZRMn7ntm2zteXgYOouTe+hSaRHMEUx
+CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRswGQYDVQQD
+ExJzdHJvbmdTd2FuIFJvb3QgQ0GCAQAwHgYDVR0RBBcwFYETZGF2ZUBzdHJvbmdz
+d2FuLm9yZzA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4u
+b3JnL3N0cm9uZ3N3YW4uY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAyAbxrpMtTARw3
+jvBwuapaHXnTppz+TkWyfXVpgTwtPlf3rbhPk4DjhT2ygyMTI1azoqProf2aBbDr
+DldCSQPsZAcuzOdruKKMo2CQwgLuBFXL+JUX0hiIpFS1ZZHA2aDKyUw4OyADOvDU
+8r1/WiwRb91TdYP9nEu9qP30k0vkUg8DCbCmPI1/MVaxVzh9LRAFyOHrnKSCXG7o
+StmVFm2Yf3pE4HS1W6DtommyPs7aUD5XAaQdr3DYKI/TazoU6t5g2aEqigu+pj2M
+qk5idJkx5VCFvUU1hlChyX6NNNjJNnV6u5YiuatcdYQhpCTBsxnBoM+w0BvNOCl+
+1PdgEy1K
+-----END CERTIFICATE-----
diff --git a/testing/hosts/dave/etc/swanctl/x509ca/strongswanCert.pem b/testing/hosts/dave/etc/swanctl/x509ca/strongswanCert.pem
new file mode 100644
index 0000000..0865ad2
--- /dev/null
+++ b/testing/hosts/dave/etc/swanctl/x509ca/strongswanCert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+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=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/default/etc/hosts b/testing/hosts/default/etc/hosts
index 75a8fdd..bcb766a 100644
--- a/testing/hosts/default/etc/hosts
+++ b/testing/hosts/default/etc/hosts
@@ -12,7 +12,7 @@
 10.1.0.254	uml1.strongswan.org	uml1
 10.2.0.254	uml1.strongswan.org	uml2
 
-10.1.0.10	alice.strongswan.org	alice aaa.strongswan.org
+10.1.0.10	alice.strongswan.org	alice aaa.strongswan.org tnc.strongswan.org
 10.1.0.20	venus.strongswan.org	venus
 10.1.0.30	carol2.strongswan.org	carol2
 10.1.0.40	dave2.strongswan.org	dave2
diff --git a/testing/hosts/default/etc/init.d/charon b/testing/hosts/default/etc/init.d/charon
new file mode 100755
index 0000000..f372fb0
--- /dev/null
+++ b/testing/hosts/default/etc/init.d/charon
@@ -0,0 +1,156 @@
+#! /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:/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
+
+# 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/hosts/moon/etc/swanctl/rsa/moonKey.pem b/testing/hosts/moon/etc/swanctl/rsa/moonKey.pem
new file mode 100755
index 0000000..4d99866
--- /dev/null
+++ b/testing/hosts/moon/etc/swanctl/rsa/moonKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAyi9jPdS7ugWGIVsVoDEvc/UzEk8LM5ua4Tu2SLArTEaODwHm
+MPvvkhl7dwj12//qfklihpZtdazxO9XkN3oYIdgt4QLq35ljtIkEGgsPn3a3niFQ
+qjkCDj+lKmd9u4ecmGKR5PFUL+LwSU6cXJVNT6p1oXqntWZS8bFu+9y0Zpf30Lf1
+ILyZAgU2WTjSzTHyvu0w52GlbALZ3ILwze/J1DRHtqmPdiiu0qwSekqVBIOPZudR
+fl4LBnLIFlR0vOaJ9zpvxuPHKyxFSY3bvAsXsEkVYG/pTyVsx3fELFNFYP+75arN
+2UTMjbTSq6+KKUr1WwOmoBpU14Qwq3g4l1PChwIDAQABAoIBACBFB/Xqajv6fbn9
+K6pxrz02uXwGmacXAtVIDoPzejWmXS4QA4l17HrJDmelSnhelDKry8nnYHkTrTz7
+mn0wQ4HDWy86o/okJUG/TKRLd6bf79aRQqqohqd3iQkHk43GyzuXH+oGioVKF0fc
+ACDWw4wfjL7FMNdHCZ4Bz9DrHO/ysHe9B6rvSYm3VZRhSxaneIkaLkkDadKpVx3f
+XNFlMxY4qKPJYYSoJZ61iMqrO7+rnA93tmyDDs8PKU3BtnpfNrdePgleJHhk8Zqy
+Ev2/NOCSUxbKE8NCtLpGTs+T0qjjnu4k3WPd3ZOBAan0uPDekHZeHB/aXGLhYcxx
+J5SurqECgYEA+F1gppkER5Jtoaudt/CUpdQ1sR9wxf75VBqJ4FiYABGQz9xlG4oj
+zL/o572s0iV3bwFpnQa+WuWrxGkP6ZuB/Z82npc0N/vLou/b4dxvg4n7K+eOOEf0
+8FMjsse2tqTIXKCqcmQnR0NPQ1jwuvEKsXP5w/JOlnRXAXnd4jxsJI0CgYEA0GaT
+61ySttUW9jC3mxuY6jkQy8TEQqR3nOFvWwmCXIWOpN/MTTPus+Telxp/pdKhU+mo
+PmX3Unyne5PvwleWDq3YzltX5ZDZGJ5UJlKuNnfGIzQ6OcHRbb7zBpQG6qSRPuug
+bgo688hTnb1L59nK88zWVK45euf6pyuoI+SwIGMCgYEA7yvE8knyhBXvezuv0z1b
+eGHmHp5/VDwY0DQKSEAoiBBiWrkLqLybgwXf/KJ8dZZc8En08aFX2GLJyYe/KiB1
+ys3ypEBJqgvRayP+o/9KZ+qNNRd0rqAksPXvL7ABNNt0kzapTSVDae3Yu6s/j1am
+DIL5qAeERIDedG5uDPpQzdUCgYB7MtjpP63ABhLv8XbpbBQnCxtByw3W89F+Xcrt
+v55gQdhE4cSuMzA/CuMH4vNpPS6AI9aBJNhj3CtKo/cOJachAGb1/wvkO5ALvLW0
+fhZdPstUTnDJain7vfF/hwzbs/PlhXgu9T9KlLfRvXFdG+Sd4g8mumRiozcLkoRw
+y6XPTwKBgDJP+s9wXmdG90HST/aqC7FKrVXLpB63dY5swNUfQP6sa0pFnON0r0JC
+h/YCsGFFIAebQ2uOkM3g3f9nkwTp7910ov+/5uThvRI2w2BBPy0mVuALPjyyF1Z2
+cb9zpyKiIuXoXRCf4sd8r1lR9bn0Fxx0Svpxf+fpMGSI5quHNBKY
+-----END RSA PRIVATE KEY-----
diff --git a/testing/hosts/moon/etc/swanctl/x509/moonCert.pem b/testing/hosts/moon/etc/swanctl/x509/moonCert.pem
new file mode 100755
index 0000000..d5c970f
--- /dev/null
+++ b/testing/hosts/moon/etc/swanctl/x509/moonCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEIjCCAwqgAwIBAgIBFzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTA5MDgyNzEwMDMzMloXDTE0MDgyNjEwMDMzMlowRjELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHDAaBgNVBAMTE21vb24u
+c3Ryb25nc3dhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDK
+L2M91Lu6BYYhWxWgMS9z9TMSTwszm5rhO7ZIsCtMRo4PAeYw+++SGXt3CPXb/+p+
+SWKGlm11rPE71eQ3ehgh2C3hAurfmWO0iQQaCw+fdreeIVCqOQIOP6UqZ327h5yY
+YpHk8VQv4vBJTpxclU1PqnWheqe1ZlLxsW773LRml/fQt/UgvJkCBTZZONLNMfK+
+7TDnYaVsAtncgvDN78nUNEe2qY92KK7SrBJ6SpUEg49m51F+XgsGcsgWVHS85on3
+Om/G48crLEVJjdu8CxewSRVgb+lPJWzHd8QsU0Vg/7vlqs3ZRMyNtNKrr4opSvVb
+A6agGlTXhDCreDiXU8KHAgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMAsGA1UdDwQE
+AwIDqDAdBgNVHQ4EFgQUapx00fiJeYn2WpTpifH6w2SdKS4wbQYDVR0jBGYwZIAU
+XafdcAZRMn7ntm2zteXgYOouTe+hSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQK
+ExBMaW51eCBzdHJvbmdTd2FuMRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GC
+AQAwHgYDVR0RBBcwFYITbW9vbi5zdHJvbmdzd2FuLm9yZzATBgNVHSUEDDAKBggr
+BgEFBQcDATA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4u
+b3JnL3N0cm9uZ3N3YW4uY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQCctXg2xeMozaTV
+jiBL1P8MY9uEH5JtU0EceQ1RbI5/2vGRdnECND9oADY5vamaaE2Mdq2Qh/vlXnML
+o3ii5ELjsQlYdTYZOcMOdcUUXYvbbFX1cwpkBhyBl1H25KptHcgQ/HnceKp3kOuq
+wYOYjgwePXulcpWXx0E2QtQCFQQZFPyEWeNJxH0oglg53QPXfHY9I2/Gukj5V0bz
+p7ME0Gs8KdnYdmbbDqzQgPsta96/m+HoJlsrVF+4Gqihj6BWMBQ2ybjPWZdG3oH9
+25cE8v60Ry98D0Z/tygbAUFnh5oOvaf642paVgc3aoA77I8U+UZjECxISoiHultY
+7QTufOwP
+-----END CERTIFICATE-----
diff --git a/testing/hosts/moon/etc/swanctl/x509ca/strongswanCert.pem b/testing/hosts/moon/etc/swanctl/x509ca/strongswanCert.pem
new file mode 100755
index 0000000..0865ad2
--- /dev/null
+++ b/testing/hosts/moon/etc/swanctl/x509ca/strongswanCert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+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=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/sun/etc/swanctl/rsa/sunKey.pem b/testing/hosts/sun/etc/swanctl/rsa/sunKey.pem
new file mode 100755
index 0000000..d8fad9a
--- /dev/null
+++ b/testing/hosts/sun/etc/swanctl/rsa/sunKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA35VUimfpDmNpT/8Q3qnoDlxJ9R+EErSYVraVoUVmH9jSHroB
+eqqtDdf3XuHtg2xKTryijBj2H0jeA7HuE1UGwmvZWN1gL5vSrk1OFrT38DmaKa/+
+mtiPqjTJrDGg+OgOz1iHsPsp/4Xx+SCTSy2Ucllfront02sVduDXEGV34Snk6vYV
+sRn1BZSlFBO6F2k23/j1i7FDn0N6Zj0hFvCysoIcfSYasmwN2p5vRqn7xC9JceMK
+3V+v0w0pZoAUBAspAjh7R1rWe08IRAt4Tzff401EGAa5+TQqoZPd4BeqvFr0AQhQ
+mdVw97FB2pQyNxSlcVvxY3NFYHwSCHcEMroWwQIDAQABAoIBADH51hjN2zk9HVgl
+QmcTAWzcUie5cLMhrP+M9mtC8O3jcCwwFY6OwfnbMU8DHy0GMqHg5lB8b99UUVPw
+HLAzjDw/ESkc6pgZs4EEhJTsxJLsvTnePgHssEgyXnXf7gRVEqJkPohfy+Zy0UCH
+eIUQXiMlOQ7xg7iDMhwNa+UdWSt539DztSKilQn2xdPZjFnMT0/prvl4NA/8Zn54
+/SdWDq5yRdLWb6EK1V7yJ3687GXR1jzGtgy7TXuncUJVTYgX7RdP1Tn6gWD8YAQ/
+RfT0DdWYm4WHSgSb9/NW8lBZH2yy3hg+lNgofXEvTfBkO5QyW31LIr0tCV6zhJIc
+Y9MxaKUCgYEA9sktaXfhPLe0ECjdeQEOq5EKuDrCviSKCOuAV4BDSOsdw6+5LWfY
+Vb/oke8N70lL3RCblcj1pOKWUi2O/SpEJdDRduiw2gM9cXt3/bChSTHC4TsIxxN/
+Db9OGg72kZ4sRY5Au+zyAAQYBwXhFWux194Jk5qK0JblNG9J5QMqZDcCgYEA5+5h
+BgHUMEO+pdME5lAiSc5PcNTejpA6j+OikCh4/HFXy3C/dLx+Cs1+egw64c8iVaIv
+NEo7n7E9I0e3XqanPRXhMnBRrP+39OVsWPmZ18Li2Hi84KwJyi8Y11l3XJOqaYpF
+wMVUuZpxR0dfG5k/5GwT/tEkmQBglOgG3m2zUMcCgYEA4m3Vd9ahV5dp5AXKpzKc
+JjiPMFfhxJo7+FEz0ZUCp03qYljBu/Jy4MKS/grrqyiCLdQGHNlk4SNxLvdUId78
+5gGBnuuDEJU2dAAIKUE9yq2YlBUZSacOxStI2snt28/X6P3LUWHm7LLU5OS1D3Vf
+mKPF/6MlSJuas5CEqVZNN+MCgYBH9Qh7IaQgmVQUBKVXg3Mv7OduvUyTdKIGtHxi
+N3xZ7hxsDP4JjNWaKmlcGmFGX8pqQRheI83d3NJ4GK8GmbP3Wst0p65fezMqsudr
+r30QmPFicgs/tYCQDw6o+aPzwAi2F+VOSqrfrtAIaldSq7hL+VA21dKB+cD9UgOX
+jPd+TwKBgQCbKeg2QNS2qhPIG9eaqJDROuxmxb/07d7OBctgMgxVvKhqW9hW42Sy
+gJ59fyz5QjFBaSfcOdf4gkKyEawVo45/q6ymIQU37R4vF4CW9Z3CfaIbwJp7LcHV
+zH07so/HNsZua6GWCSCLJU5MeCRiZzk2RFiS9KIaLP4gZndv4lXOiQ==
+-----END RSA PRIVATE KEY-----
diff --git a/testing/hosts/sun/etc/swanctl/x509/sunCert.pem b/testing/hosts/sun/etc/swanctl/x509/sunCert.pem
new file mode 100755
index 0000000..d0937ba
--- /dev/null
+++ b/testing/hosts/sun/etc/swanctl/x509/sunCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIBFjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTA5MDgyNzA5NTkwNFoXDTE0MDgyNjA5NTkwNFowRTELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN1bi5z
+dHJvbmdzd2FuLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+V
+VIpn6Q5jaU//EN6p6A5cSfUfhBK0mFa2laFFZh/Y0h66AXqqrQ3X917h7YNsSk68
+oowY9h9I3gOx7hNVBsJr2VjdYC+b0q5NTha09/A5mimv/prYj6o0yawxoPjoDs9Y
+h7D7Kf+F8fkgk0stlHJZX66J7dNrFXbg1xBld+Ep5Or2FbEZ9QWUpRQTuhdpNt/4
+9YuxQ59DemY9IRbwsrKCHH0mGrJsDdqeb0ap+8QvSXHjCt1fr9MNKWaAFAQLKQI4
+e0da1ntPCEQLeE833+NNRBgGufk0KqGT3eAXqrxa9AEIUJnVcPexQdqUMjcUpXFb
+8WNzRWB8Egh3BDK6FsECAwEAAaOCARkwggEVMAkGA1UdEwQCMAAwCwYDVR0PBAQD
+AgOoMB0GA1UdDgQWBBRW1p4v2qihzRlcI1PnxbZwluML+zBtBgNVHSMEZjBkgBRd
+p91wBlEyfue2bbO15eBg6i5N76FJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoT
+EExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIB
+ADAdBgNVHREEFjAUghJzdW4uc3Ryb25nc3dhbi5vcmcwEwYDVR0lBAwwCgYIKwYB
+BQUHAwEwOQYDVR0fBDIwMDAuoCygKoYoaHR0cDovL2NybC5zdHJvbmdzd2FuLm9y
+Zy9zdHJvbmdzd2FuLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAo37LYT9Awx0MK/nA
+FZpPJqUr0Ey+O5Ukcsdx7nd00SlmpiQRY8KmuRXCBQnDEgdLstd3slQjT0pJEgWF
+0pzxybnI6eOzYAhLfhart+X1hURiNGbXjggm2s4I5+K32bVIkNEqlsYnd/6F9oo5
+ZNO0/eTTruLZfkNe/zchBGKe/Z7MacVwlYWWCbMtBV4K1d5dGcRRgpQ9WivDlmat
+Nh9wlscDSgSGk3HJkbxnq695VN7zUbDWAUvWWhV5bIDjlAR/xyT9ApqIxiyVVRul
+fYrE7U05Hbt6GgAroAKLp6qJup9+TxQAKSjKIwJ0hf7OuYyQ8TZtVHS7AOhm+T/5
+G/jGGA==
+-----END CERTIFICATE-----
diff --git a/testing/hosts/sun/etc/swanctl/x509ca/strongswanCert.pem b/testing/hosts/sun/etc/swanctl/x509ca/strongswanCert.pem
new file mode 100755
index 0000000..0865ad2
--- /dev/null
+++ b/testing/hosts/sun/etc/swanctl/x509ca/strongswanCert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+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=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/venus/etc/swanctl/rsa/venusKey.pem b/testing/hosts/venus/etc/swanctl/rsa/venusKey.pem
new file mode 100644
index 0000000..0477f69
--- /dev/null
+++ b/testing/hosts/venus/etc/swanctl/rsa/venusKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAs0UsstkyjuvNkpx/vmZlKpBITJyGmfTfFjl01uU4dUVwzE3y
+hllGPLN3ijLSteHP3opUbDNd5dG4eVsa9DUiqIJlk/g+tnKS5IdQbA6yUf1nIHr3
+9tVukOtX66sMeHBU+M46KD7r4RRrGSBYT1FsyIv47D2uk24nBZ7Sf2+LoVQZfMIV
+dydIGfHxmQJxymzS80mh57EN2y70oH9HMwn/bbGb8WrysN09WVbNbT2vdeYX3OJX
+i0xsmT/Ynev1VD9B2mbA/XCf4c45xFL1HxKQ/+RTlmY6z6m4rBFuFGCscLPba5g2
+90mXqrpMSpuWUagIRZmOaeoyd3x25qbYwNe5QwIDAQABAoIBAC9F9I2NHPn3UJRy
+1HTfB5p7xbT+Kbh7jECOEjOA6qxyDVayz1uCOzVSlhlJYas4ytoCXFTUDtTFwwGt
+dqQjRupsyGCGu/Lcr8O3swtrrLZWPlWgV7ctfSSWCu9IgddYt++MYmWuggEuozdT
+AjaYYDlaP9/8PAcAqyWeRh/4yDdYRpEHshePE/uZaIDH1xgQ72v8Ks6fnz3sTYK6
+dJZfZ2EMUS2CsdbqYX+X7CSLkM7FVs+O0xFz00AF7xyfID9RP+nSGkPny60/O5Vk
+qO3dC1pXCs3aAXlTUBsP0aHWHFHXIIfJA95fQy0V7gqDxXHRPRInlFdERYkebM4S
+ctnfxYECgYEA6vFH8Vzc9G99LIZGX2EfODfwJ62TzDPOgqubUMpQRqydTxA9GaPG
+KyoF7GEYK3K8sji/uH1qcogUS46vXNcvm5xe7B5OPgfTLF6tfMaVeBvA6PfGOirx
+qzvrFDTp+DdInOOO9KwvVULKvWtIehSIT12EjKXPxnMCh/vTN2ngg2ECgYEAw1aA
+Z7iBrOPSTFf3S+rMgEMSv3s578YTg6hlaNfDvTEC9zQEDg7k4MxffRyBKLqidLUl
+ZZrcTszdO25c56w7xjFwcLwlFZuaoulFn+ON77/eudtCAjGjnmxUQuruzmoh8YyL
+zBB0oEGzm4u46BK3/ODIzQxpZL0MUUTXliLfoyMCgYA5KwrxfUI6rGJOEkJPdSeO
+m3XxgbgkCTsn6q/5YbFU8S26Dl5/va071ZbpZNrnv5yQ1WQ5dTMQuXIOzKJ5OddY
+yx0B4YHycB7/fe5DHWNDfaVcSuZOQyLZItRZ72I7RuCBZJHlkXxXB9CjdNaG9jYQ
+8dWOD87WICguhKVpp3a9IQKBgGLZByl1iMmAkA7qBM56Bvpw9q/HH85iIcXiFU80
+wGygvKtzuwmSJ+hKA5hAMGv35fXBJSeBcjK+IMXOV101HxpwMkIaM3n3wAzolr8O
+W+kS4xaSCZkqnW2xzAIA+M+jjYG6aZPeT+Y42TbBQdTOhCSHa5W3zi2YLP+DIsVq
+6FiZAoGAUGZttRZOFMZ1paEKtJzvbf7bYNkqW1iIY5AVAN84g4AEJ3910WHxXh7+
+uFWyBU4fUy0Qgk9HihSRbfnq2lvwNNWUeMQmt8t1WpEGUDT6FH4LoDD3fvHbmxY0
+y5QBbDvalkeIe6ESdW1uhLzxCzCRZSkANtMfiVCKvQOOBjxbfeo=
+-----END RSA PRIVATE KEY-----
diff --git a/testing/hosts/venus/etc/swanctl/x509/venusCert.pem b/testing/hosts/venus/etc/swanctl/x509/venusCert.pem
new file mode 100644
index 0000000..c383667
--- /dev/null
+++ b/testing/hosts/venus/etc/swanctl/x509/venusCert.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBGDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTA5MDgyNzEwMDUyMloXDTE0MDgyNjEwMDUyMlowRzELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHTAbBgNVBAMTFHZlbnVz
+LnN0cm9uZ3N3YW4ub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+s0UsstkyjuvNkpx/vmZlKpBITJyGmfTfFjl01uU4dUVwzE3yhllGPLN3ijLSteHP
+3opUbDNd5dG4eVsa9DUiqIJlk/g+tnKS5IdQbA6yUf1nIHr39tVukOtX66sMeHBU
++M46KD7r4RRrGSBYT1FsyIv47D2uk24nBZ7Sf2+LoVQZfMIVdydIGfHxmQJxymzS
+80mh57EN2y70oH9HMwn/bbGb8WrysN09WVbNbT2vdeYX3OJXi0xsmT/Ynev1VD9B
+2mbA/XCf4c45xFL1HxKQ/+RTlmY6z6m4rBFuFGCscLPba5g290mXqrpMSpuWUagI
+RZmOaeoyd3x25qbYwNe5QwIDAQABo4IBBjCCAQIwCQYDVR0TBAIwADALBgNVHQ8E
+BAMCA6gwHQYDVR0OBBYEFI9cCmyxR/wbUXCARuBjbHpUAS1nMG0GA1UdIwRmMGSA
+FF2n3XAGUTJ+57Zts7Xl4GDqLk3voUmkRzBFMQswCQYDVQQGEwJDSDEZMBcGA1UE
+ChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBSb290IENB
+ggEAMB8GA1UdEQQYMBaCFHZlbnVzLnN0cm9uZ3N3YW4ub3JnMDkGA1UdHwQyMDAw
+LqAsoCqGKGh0dHA6Ly9jcmwuc3Ryb25nc3dhbi5vcmcvc3Ryb25nc3dhbi5jcmww
+DQYJKoZIhvcNAQELBQADggEBAK5Pi/g5Y234tEcTFWE0Vdg4cKxIfZRewFOOZI1z
+/RWfzoqPZ6YzD15B1toKZrAGsqyhdJ4yQ/BwxJpdgNCscMelkzMubcLXL9QugPS4
+hz4MLkJR2tDCZA/mFUTEbAQwdNSCxSo/l0vZ5KXUg9y5zZhCWpZiHJBXnz/567wn
+K16J3x9TYtdh4sT+y+0vHgvosUs2srRTkK2WDDxlh9XTch7DZyrLuiRRFrWjc6y9
+ThVH/qQNXwEBq2t9UYjQUVyx77gVQmiLrPU7UjL4IBoZmBNV/VJ10+rmGj1eG1nD
+pgq6oBTrbEsv8Ix7y/MziTB8POj3dKjl2UZmRVBwMbnNqYk=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/venus/etc/swanctl/x509ca/strongswanCert.pem b/testing/hosts/venus/etc/swanctl/x509ca/strongswanCert.pem
new file mode 100644
index 0000000..0865ad2
--- /dev/null
+++ b/testing/hosts/venus/etc/swanctl/x509ca/strongswanCert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+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=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/winnetou/etc/openssl/index.txt b/testing/hosts/winnetou/etc/openssl/index.txt
index 5958a13..4b75f47 100644
--- a/testing/hosts/winnetou/etc/openssl/index.txt
+++ b/testing/hosts/winnetou/etc/openssl/index.txt
@@ -17,8 +17,8 @@ R	111007105811Z	111017123709Z,superseded	10	unknown	/C=CH/O=Linux strongSwan/OU=
 R	111007121250Z	111017123712Z,superseded	11	unknown	/C=CH/O=Linux strongSwan/OU=SHA-384/CN=carol at strongswan.org
 R	111007122112Z	111017123715Z,superseded	12	unknown	/C=CH/O=Linux strongSwan/OU=SHA-512/CN=dave at strongswan.org
 R	120224075857Z	120315063217Z,superseded	13	unknown	/C=CH/O=Linux strongSwan/OU=OCSP/CN=carol at strongswan.org
-V	120425210745Z		14	unknown	/C=CH/O=Linux strongSwan/CN=winnetou.strongswan.org
-V	140406120117Z		15	unknown	/C=CH/O=Linux strongSwan/OU=Research/serialNumber=002/CN=carol at strongswan.org
+R	120425210745Z	140414203104Z,superseded	14	unknown	/C=CH/O=Linux strongSwan/CN=winnetou.strongswan.org
+R	140406120117Z	140414203012Z,superseded	15	unknown	/C=CH/O=Linux strongSwan/OU=Research/serialNumber=002/CN=carol at strongswan.org
 V	140826095904Z		16	unknown	/C=CH/O=Linux strongSwan/CN=sun.strongswan.org
 V	140826100332Z		17	unknown	/C=CH/O=Linux strongSwan/CN=moon.strongswan.org
 V	140826100522Z		18	unknown	/C=CH/O=Linux strongSwan/CN=venus.strongswan.org
@@ -38,3 +38,4 @@ V	161015124759Z		25	unknown	/C=CH/O=Linux strongSwan/OU=SHA-384/CN=carol at strongs
 V	161015125030Z		26	unknown	/C=CH/O=Linux strongSwan/OU=SHA-512/CN=dave at strongswan.org
 V	170314064200Z		27	unknown	/C=CH/O=Linux strongSwan/OU=OCSP/CN=carol at strongswan.org
 R	190321135622Z	140322135700Z,CACompromise	28	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Research CA
+V	190413204655Z		29	unknown	/C=CH/O=Linux strongSwan/OU=Research/serialNumber=002/CN=carol at strongswan.org
diff --git a/testing/hosts/winnetou/etc/openssl/index.txt.old b/testing/hosts/winnetou/etc/openssl/index.txt.old
index a6d5a08..3baf17f 100644
--- a/testing/hosts/winnetou/etc/openssl/index.txt.old
+++ b/testing/hosts/winnetou/etc/openssl/index.txt.old
@@ -17,8 +17,8 @@ R	111007105811Z	111017123709Z,superseded	10	unknown	/C=CH/O=Linux strongSwan/OU=
 R	111007121250Z	111017123712Z,superseded	11	unknown	/C=CH/O=Linux strongSwan/OU=SHA-384/CN=carol at strongswan.org
 R	111007122112Z	111017123715Z,superseded	12	unknown	/C=CH/O=Linux strongSwan/OU=SHA-512/CN=dave at strongswan.org
 R	120224075857Z	120315063217Z,superseded	13	unknown	/C=CH/O=Linux strongSwan/OU=OCSP/CN=carol at strongswan.org
-V	120425210745Z		14	unknown	/C=CH/O=Linux strongSwan/CN=winnetou.strongswan.org
-V	140406120117Z		15	unknown	/C=CH/O=Linux strongSwan/OU=Research/serialNumber=002/CN=carol at strongswan.org
+R	120425210745Z	140414203104Z,superseded	14	unknown	/C=CH/O=Linux strongSwan/CN=winnetou.strongswan.org
+R	140406120117Z	140414203012Z,superseded	15	unknown	/C=CH/O=Linux strongSwan/OU=Research/serialNumber=002/CN=carol at strongswan.org
 V	140826095904Z		16	unknown	/C=CH/O=Linux strongSwan/CN=sun.strongswan.org
 V	140826100332Z		17	unknown	/C=CH/O=Linux strongSwan/CN=moon.strongswan.org
 V	140826100522Z		18	unknown	/C=CH/O=Linux strongSwan/CN=venus.strongswan.org
@@ -37,4 +37,4 @@ V	161015124507Z		24	unknown	/C=CH/O=Linux strongSwan/OU=SHA-224/CN=moon.strongsw
 V	161015124759Z		25	unknown	/C=CH/O=Linux strongSwan/OU=SHA-384/CN=carol at strongswan.org
 V	161015125030Z		26	unknown	/C=CH/O=Linux strongSwan/OU=SHA-512/CN=dave at strongswan.org
 V	170314064200Z		27	unknown	/C=CH/O=Linux strongSwan/OU=OCSP/CN=carol at strongswan.org
-V	190321135622Z		28	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Research CA
+R	190321135622Z	140322135700Z,CACompromise	28	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Research CA
diff --git a/testing/hosts/winnetou/etc/openssl/newcerts/29.pem b/testing/hosts/winnetou/etc/openssl/newcerts/29.pem
new file mode 100644
index 0000000..a4d9812
--- /dev/null
+++ b/testing/hosts/winnetou/etc/openssl/newcerts/29.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIBKTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTE0MDQxNDIwNDY1NVoXDTE5MDQxMzIwNDY1NVowaDELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAPBgNVBAsTCFJlc2Vh
+cmNoMQwwCgYDVQQFEwMwMDIxHTAbBgNVBAMUFGNhcm9sQHN0cm9uZ3N3YW4ub3Jn
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzXQSXX8LtY/RlgvQxxCF
+pq787RPVD1HQciKemGkzUcjC+J+3rHBKmPT68Prb/4j9ESYdPqvaI7KWGD7pkAv4
+BWv4rw5iAxKB7bEDSVg5Gjs9vXDifR27Pz8rfsQFo8+O9oYWb7Ah45TNU/B8+Pcr
+Gajv0I7eHUbGJsKlgOOMBkSe3cbQd9jc54iv8AFFfMsh5riMz2+7LI8zaMzie3vN
+aPjsSDcGTB7jDa9bY+ZMbHzdFaDzmodDrZNJOSKTeDp5QTuP/JTPrSCXiIqUEJbE
+IUhWF2P1s8wH9SeW0ZQlw4Z0eETR/c7XQfzdJj7UCmWLJQ//eseoAXNc1DbV6EtJ
+1QIDAQABo4IBBjCCAQIwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwHQYDVR0OBBYE
+FGkt9dMYc1d/MRpfoo1q6zzwdBDMMG0GA1UdIwRmMGSAFF2n3XAGUTJ+57Zts7Xl
+4GDqLk3voUmkRzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25n
+U3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBSb290IENBggEAMB8GA1UdEQQYMBaB
+FGNhcm9sQHN0cm9uZ3N3YW4ub3JnMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9j
+cmwuc3Ryb25nc3dhbi5vcmcvc3Ryb25nc3dhbi5jcmwwDQYJKoZIhvcNAQELBQAD
+ggEBAEbfq0PDdexYL9OqqD1Q8U0UXIRi3hvruqGM+KW8UbKisRqJJnow5wCYBJLI
+MFC7ze24AcADe0Az+uLdKzClVZ+87i/vMse0dCGxSvKKwUtI9bFeQOourrBEHHRw
+xJJcY9eGlsJoyJXyuT8sEXI+YqAaVDtcAYDa+OjIQNrJeIZDv9t/+1q1wlh0gvIz
+zfndSfL4xEIf+lw1Flvt8BwTx4jDk6QIS4jUO3YtHzrtZ+171/iqmSvGrEmfVceq
+1KOn7zNgh7XHmqE92HU63R9sVu3zjVSzuAMIVDqT5v8qU6T85NJE8ebYXi/RL8ON
+btGZ7+y4Z4CbdkjLZ+Oxtew0nwk=
+-----END CERTIFICATE-----
diff --git a/testing/hosts/winnetou/etc/openssl/serial b/testing/hosts/winnetou/etc/openssl/serial
index f04c001..8676c24 100644
--- a/testing/hosts/winnetou/etc/openssl/serial
+++ b/testing/hosts/winnetou/etc/openssl/serial
@@ -1 +1 @@
-29
+2A
diff --git a/testing/hosts/winnetou/etc/openssl/serial.old b/testing/hosts/winnetou/etc/openssl/serial.old
index 9902f17..f04c001 100644
--- a/testing/hosts/winnetou/etc/openssl/serial.old
+++ b/testing/hosts/winnetou/etc/openssl/serial.old
@@ -1 +1 @@
-28
+29
diff --git a/testing/scripts/build-baseimage b/testing/scripts/build-baseimage
index b6b8854..956fc93 100755
--- a/testing/scripts/build-baseimage
+++ b/testing/scripts/build-baseimage
@@ -17,7 +17,9 @@ INC=$INC,openssl,vim,sqlite3,conntrack,gdb,cmake,libxerces-c2-dev,libltdl-dev
 INC=$INC,liblog4cxx10-dev,libboost-thread-dev,libboost-system-dev,git-core
 INC=$INC,less,acpid,acpi-support-base,libldns-dev,libunbound-dev,dnsutils,screen
 INC=$INC,gnat,gprbuild,libahven3-dev,libxmlada4.1-dev,libgmpada3-dev
-INC=$INC,libalog0.4.1-base-dev,hostapd,libsoup2.4-dev
+INC=$INC,libalog0.4.1-base-dev,hostapd,libsoup2.4-dev,ca-certificates,unzip
+INC=$INC,python,python-setuptools,python-dev,python-pip
+INC=$INC,libjson0-dev,libxslt1-dev,libapache2-mod-wsgi
 SERVICES="apache2 dbus isc-dhcp-server slapd bind9"
 INC=$INC,${SERVICES// /,}
 
diff --git a/testing/scripts/build-guestimages b/testing/scripts/build-guestimages
index f7fb1f8..245fc25 100755
--- a/testing/scripts/build-guestimages
+++ b/testing/scripts/build-guestimages
@@ -48,7 +48,14 @@ do
 	execute "cp -rf $HOSTSDIR/default/* $LOOPDIR" 0
 	execute_chroot "ldconfig" 0
 
-	if [ "$host" = "winnetou" ]
+	if [ "$host" = "alice" ]
+	then
+		execute "mkdir $LOOPDIR/var/log/apache2/tnc" 0
+		execute "mkdir $LOOPDIR/etc/pts" 0
+		execute_chroot "chgrp www-data /etc/pts" 0
+		execute_chroot "chmod g+w /etc/pts" 0
+	fi
+    if [ "$host" = "winnetou" ]
 	then
 		execute "mkdir $LOOPDIR/var/log/apache2/ocsp" 0
 		execute "cp -rf $DIR/../images $LOOPDIR/var/www/" 0
diff --git a/testing/scripts/recipes/014_swid_generator.mk b/testing/scripts/recipes/014_swid_generator.mk
new file mode 100644
index 0000000..5891469
--- /dev/null
+++ b/testing/scripts/recipes/014_swid_generator.mk
@@ -0,0 +1,16 @@
+#!/usr/bin/make
+
+PKG = swidGenerator
+ZIP = $(PKG)-master.zip
+SRC = https://github.com/strongswan/$(PKG)/archive/master.zip
+
+all: install
+
+$(ZIP):
+	wget --ca-directory="/usr/share/ca-certificates/mozilla" $(SRC) -O $(ZIP)
+
+$(PKG)-master: $(ZIP)
+	unzip $(ZIP)
+
+install: $(PKG)-master
+	cd $(PKG)-master && python setup.py install
diff --git a/testing/scripts/recipes/015_strongTNC.mk b/testing/scripts/recipes/015_strongTNC.mk
new file mode 100644
index 0000000..cc4a94a
--- /dev/null
+++ b/testing/scripts/recipes/015_strongTNC.mk
@@ -0,0 +1,22 @@
+#!/usr/bin/make
+
+PKG = strongTNC
+ZIP = $(PKG)-master.zip
+SRC = https://github.com/strongswan/$(PKG)/archive/master.zip
+DEPS = $(PKG)-deps
+
+all: install
+
+$(ZIP):
+	wget --ca-directory=/usr/share/ca-certificates/mozilla/ $(SRC) -O $(ZIP)
+
+$(PKG)-master: $(ZIP)
+	unzip -u $(ZIP)
+
+$(DEPS): $(PKG)-master
+	mkdir -p $(DEPS)
+	pip install --download $(DEPS) -r $(PKG)-master/requirements.txt
+
+install: $(DEPS)
+	pip install --no-index --find-links=file://`pwd`/$(DEPS) -r $(PKG)-master/requirements.txt
+	cp -r $(PKG)-master /var/www/tnc && chgrp -R www-data /var/www/tnc && chmod g+w /var/www/tnc /var/www/tnc/django.db
diff --git a/testing/testing.conf b/testing/testing.conf
index 8e0c81e..f5e65b2 100644
--- a/testing/testing.conf
+++ b/testing/testing.conf
@@ -24,14 +24,14 @@ fi
 : ${TESTDIR=/srv/strongswan-testing}
 
 # Kernel configuration
-: ${KERNELVERSION=3.13.2}
+: ${KERNELVERSION=3.15.1}
 : ${KERNEL=linux-$KERNELVERSION}
 : ${KERNELTARBALL=$KERNEL.tar.xz}
-: ${KERNELCONFIG=$DIR/../config/kernel/config-3.13}
-: ${KERNELPATCH=ha-3.13-abicompat.patch.bz2}
+: ${KERNELCONFIG=$DIR/../config/kernel/config-3.15}
+: ${KERNELPATCH=ha-3.15-ah-abicompat.patch.bz2}
 
 # strongSwan version used in tests
-: ${SWANVERSION=5.1.2}
+: ${SWANVERSION=5.2.0}
 
 # Build directory where the guest kernel and images will be built
 : ${BUILDDIR=$TESTDIR/build}
@@ -50,11 +50,11 @@ fi
 
 # Base image settings
 # The base image is a pristine OS installation created using debootstrap.
-: ${BASEIMGSIZE=1280}
+: ${BASEIMGSIZE=1400}
 : ${BASEIMGSUITE=wheezy}
 : ${BASEIMGARCH=amd64}
 : ${BASEIMG=$IMGDIR/debian-$BASEIMGSUITE-$BASEIMGARCH.$IMGEXT}
-: ${BASEIMGMIRROR=http://cdn.debian.net/debian}
+: ${BASEIMGMIRROR=http://http.debian.net/debian}
 
 # Root image settings
 # The root image is the origin of all guest images. It is a clone of the base
diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/aacerts/aa.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/aacerts/aa.pem
new file mode 100644
index 0000000..fbfa7ee
--- /dev/null
+++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/aacerts/aa.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
+Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx
+CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD
+Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH
+hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP
+dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L
+lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/
+QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N
+jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2
+bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM
+ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik
+gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02
+R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA
+6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g
+91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ==
+-----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/carol-sales-finance.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/carol-sales-finance.pem
new file mode 100644
index 0000000..406c157
--- /dev/null
+++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/carol-sales-finance.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC+DCCAeACAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
+pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
+BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
+MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
+MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIWCKrRUelL+kw
+IhgPMjAxNDAyMDcwODU4MTJaGA8yMDIyMDQyNjA4NTgxMlowIjAgBggrBgEFBQcK
+BDEUMBIwEAwFc2FsZXMMB2ZpbmFuY2UwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh
+2q7CV/ZSsLChSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJv
+bmdTd2FuMRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkG
+A1UdOAQCBQAwDQYJKoZIhvcNAQEFBQADggEBADNSv52dbBOp30L0kJse9HqWMBaR
+SA5IDrF1FMLVZfI0Vb9XgEmk1SXAnMmPm7bfk+2w0Rd1jL7D905nel3LXuvohSR9
+wd4Vo8XX3WUlzNfjUEFFJb0nU2ybr7SmxF+K4wGnhvBAym2y/hNA0glp2hNjYTds
+g+RUpM4bSqP5DpUfRBl19VHeEu/OymoACOzuHuNc1IndYM1mkSJYumX6YW60DpF/
+TaK1So3FyEWucHeoFCziNbclrjWwB8OS3JfCOl95rxu+0JhyWc+3x1E50W8DaAnY
+ZRyYxDjYT9/E9xyzV45yo0xFODIgDgfKMsDjfUmfny3dTesdFUf3Ar3vTfA=
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-marketing.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-marketing.pem
new file mode 100644
index 0000000..2f646c3
--- /dev/null
+++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-marketing.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC9DCCAdwCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
+pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
+BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
+RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
+FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCCPxWgWKmOUM
+MCIYDzIwMTQwMjA3MDg1OTM3WhgPMjAyMjA0MjYwODU5MzdaMB0wGwYIKwYBBQUH
+CgQxDzANMAsMCW1hcmtldGluZzB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX
+9lKwsKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3
+YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04
+BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAThlKhGVv34sfnCSQn6nYUdxMhboTuC98
++DgvTQ/tH0hddCJNg00SpO8AbStwEsqHFaSqFzAGHcMk+XUrBRSGszAwg8nKAKfT
+MCvJbK6lWQcPF0WPSSk9/r1TLan4I9xhneNIIGQf1fnNo7NrQnmhJjolUgXQNwFA
+qZgKBsk0jWcOSvI0bpK90km5flCHn/OA1rDCdaPuMwreDhvNDoApORYFPZVsLhid
+CXSqT+FWfm2NfegS+Q4VHP3YLbY4vLepCerU9aMTUIPit0kf1N8piG/l6AUno1XP
+VrcTvruQUWQb08H9aYt7l7kyhzOKkuXjVbdn5egZnK0m4WKmV50guA==
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-sales-expired.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-sales-expired.pem
new file mode 100644
index 0000000..d420384
--- /dev/null
+++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-sales-expired.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC8DCCAdgCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
+pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
+BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
+RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
+FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCEuGbFvrRrtr
+MCIYDzIwMTQwMjA3MDgwMTE3WhgPMjAxNDAyMDcwOTAxMTdaMBkwFwYIKwYBBQUH
+CgQxCzAJMAcMBXNhbGVzMH8wcgYDVR0jBGswaQsB6sc6Alz4tsTB4dquwlf2UrCw
+oUmkRzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEb
+MBkGA1UEAxMSc3Ryb25nU3dhbiBSb290IENBgggVTn4VrxwXYTAJBgNVHTgEAgUA
+MA0GCSqGSIb3DQEBBQUAA4IBAQBYnOq716FJ079kXAt8vmi2GpEyyCqSBqqjr0lR
+X9mGQqWKmpj88ZP61tCooCy8HaJsgKBvedKJHJ4e/YxR+fqBDkT4apFu4wX8P/xh
+yKy6/RMAdTtkwVTE6flXdQryCQ/PGhSMuwwH/URFg65mixAatyyaoat4+mZ506u3
+F9ZZXkHPP4nZXAJqYjLLcNXPqC4lGoXXT+9dgsm6RLAdnBXT1GGff9tmqt9CcspW
+XPjoqy9AxNr6FnItvMGw0CC6MPyVOJImlSxdhFW7waZkpNfmGzRdylXMwHXk8PbW
+gjmlDUbyWquu8xBlpron3X/Jx3YNGVNrhgfZLlmhzCRouMqc
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/private/aa.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/private/aa.pem
new file mode 100644
index 0000000..a4e0017
--- /dev/null
+++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/private/aa.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF
+FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA
+Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY
+zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT
+jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf
++7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+
+eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz
+d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn
+DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB
+01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot
+mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK
+vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM
+lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH
+mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i
+xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf
+3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo
+vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/
+zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S
+Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ
+3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV
+oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+
+XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N
+GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV
+2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3
+RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4=
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-finance-expired.pem b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-finance-expired.pem
new file mode 100644
index 0000000..3be000a
--- /dev/null
+++ b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-finance-expired.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC8TCCAdkCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
+pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
+BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
+MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
+MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIISLuuiWM2O9Yw
+IhgPMjAxNDAyMDcwODQyMDVaGA8yMDE0MDIwNzA5NDIwNVowGzAZBggrBgEFBQcK
+BDENMAswCQwHZmluYW5jZTB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX9lKw
+sKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
+GzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04BAIF
+ADANBgkqhkiG9w0BAQUFAAOCAQEAaDwqM5BY9pXhlSlT3cpCJYsNCfk6T1nG5s5J
+Dtgwojw0BVSoxKqcbpWdP09HOpBcwbPVk++I19wd5VsdHxtQ4/o2Hoevg4QWxUUx
+t3qsdMDjg7U2iH+JppYsEDmXmx9k1hvV1OiEzHJKTDlZqXkhiItLatKSptTG3c0A
+DdJVS05sdepzhkRGimE/QwO7nJ3v5ixFNIetgfbojbjhJPpNfXPIgMMHerK/hAlo
+ekSwcmh9ufFuEXg8C0NunQqf6Z6FbxiUXUF9j7dvlEp3n5YFsv3WSMUjE3Sb7r8T
+3e2A/LXb05ky0/SNebgS4fU9oi8acEgwN2Vqwu82hClwYAcHJg==
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem
new file mode 100644
index 0000000..a188a1d
--- /dev/null
+++ b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC7zCCAdcCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
+pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
+BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
+MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
+MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIYO/yp98Yxu4w
+IhgPMjAxNDAyMDcxMDAxNTdaGA8yMDIyMDQyNjEwMDE1N1owGTAXBggrBgEFBQcK
+BDELMAkwBwwFc2FsZXMwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh2q7CV/ZSsLCh
+SaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRsw
+GQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkGA1UdOAQCBQAw
+DQYJKoZIhvcNAQEFBQADggEBAJA/duSysWae5X9JTC0BLY6gK8ggj5V9H3d60rM4
+7A8HVQldWe5QwYIRZmLS0XhMVHWiIvXJHwue2Xgs8DyAqILSCKIKpCJRhqPIxHCh
+bek1nzw2YzVaU+E37He5V9PSkkRFO9tRvELhW3t4Wya7p4l6MVFW9ETOOtUqZYmt
+bxAq/XEFZl/aFb2FW2RoKjUZpwxbrccCaV1hKIxtNen2ro31dNd9YHXe+fE4Fc7r
+FTwbhOg3QLvZDXmiZt3LCXdMKAhayLbuSVsycuEtac44OVSvKhJ8GYykTRRn67nU
+qCFNDe266KTNDqUMilrHm3FYGkpFtREOBajH4EqdMAJSdXg=
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/aacerts/aa.pem b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/aacerts/aa.pem
new file mode 100644
index 0000000..fbfa7ee
--- /dev/null
+++ b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/aacerts/aa.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
+Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx
+CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD
+Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH
+hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP
+dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L
+lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/
+QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N
+jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2
+bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM
+ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik
+gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02
+R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA
+6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g
+91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ==
+-----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/private/aa.pem b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/private/aa.pem
new file mode 100644
index 0000000..a4e0017
--- /dev/null
+++ b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/private/aa.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF
+FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA
+Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY
+zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT
+jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf
++7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+
+eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz
+d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn
+DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB
+01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot
+mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK
+vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM
+lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH
+mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i
+xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf
+3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo
+vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/
+zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S
+Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ
+3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV
+oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+
+XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N
+GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV
+2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3
+RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4=
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem b/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem
new file mode 100644
index 0000000..a188a1d
--- /dev/null
+++ b/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC7zCCAdcCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
+pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
+BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
+MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
+MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIYO/yp98Yxu4w
+IhgPMjAxNDAyMDcxMDAxNTdaGA8yMDIyMDQyNjEwMDE1N1owGTAXBggrBgEFBQcK
+BDELMAkwBwwFc2FsZXMwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh2q7CV/ZSsLCh
+SaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRsw
+GQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkGA1UdOAQCBQAw
+DQYJKoZIhvcNAQEFBQADggEBAJA/duSysWae5X9JTC0BLY6gK8ggj5V9H3d60rM4
+7A8HVQldWe5QwYIRZmLS0XhMVHWiIvXJHwue2Xgs8DyAqILSCKIKpCJRhqPIxHCh
+bek1nzw2YzVaU+E37He5V9PSkkRFO9tRvELhW3t4Wya7p4l6MVFW9ETOOtUqZYmt
+bxAq/XEFZl/aFb2FW2RoKjUZpwxbrccCaV1hKIxtNen2ro31dNd9YHXe+fE4Fc7r
+FTwbhOg3QLvZDXmiZt3LCXdMKAhayLbuSVsycuEtac44OVSvKhJ8GYykTRRn67nU
+qCFNDe266KTNDqUMilrHm3FYGkpFtREOBajH4EqdMAJSdXg=
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-expired-aa.pem b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-expired-aa.pem
new file mode 100644
index 0000000..e612607
--- /dev/null
+++ b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-expired-aa.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC7TCCAdUCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
+pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
+BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
+QzBBpD8wPTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
+EzARBgNVBAMTCmV4cGlyZWQgQUEwDQYJKoZIhvcNAQEFBQACCG25qKzXgZ9HMCIY
+DzIwMTQwMjA3MTAxMzQyWhgPMjAyMjA0MjYxMDEzNDJaMBkwFwYIKwYBBQUHCgQx
+CzAJMAcMBXNhbGVzMH8wcgYDVR0jBGswabOoTOBJ6lXcG4NAowI32Y/oXa9/oUmk
+RzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkG
+A1UEAxMSc3Ryb25nU3dhbiBSb290IENBgggqIkNljRd9CTAJBgNVHTgEAgUAMA0G
+CSqGSIb3DQEBBQUAA4IBAQCfX/84tHCidlVbOU4is/1hZc+FpK4GG1jcywM9mtjB
+QUeX28LYkewDdRpe49zJuTbvuIIABTp+4alf/oo7sKLk+o2/qq6CPfx8BSRL1a61
+Y1wVeGmXqcRQgtX+r3asMtLBoAFO8VaHt6pY52bg2YMNVRrUnCUVLqQjT+/Ujr4f
+Lhs74VOxn7S94YbqvP5rytNFjdzBREipmb8j4mhIyfwUluoWFCkzxuwRaSEGhSMO
+NobJuj/mK0PUU+TMYEcOMpQ/nVyb9rBtOvDoNU3BeD+ovuamErT9/9vWhEOwMD4C
+OeR+ofespDX+AdCyZ1Dr1GMyUmIRK7GERdasIhx5pYMk
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-marketing.pem b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-marketing.pem
new file mode 100644
index 0000000..2f646c3
--- /dev/null
+++ b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-marketing.pem
@@ -0,0 +1,18 @@
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIC9DCCAdwCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
+bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
+pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
+BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
+RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
+FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCCPxWgWKmOUM
+MCIYDzIwMTQwMjA3MDg1OTM3WhgPMjAyMjA0MjYwODU5MzdaMB0wGwYIKwYBBQUH
+CgQxDzANMAsMCW1hcmtldGluZzB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX
+9lKwsKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3
+YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04
+BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAThlKhGVv34sfnCSQn6nYUdxMhboTuC98
++DgvTQ/tH0hddCJNg00SpO8AbStwEsqHFaSqFzAGHcMk+XUrBRSGszAwg8nKAKfT
+MCvJbK6lWQcPF0WPSSk9/r1TLan4I9xhneNIIGQf1fnNo7NrQnmhJjolUgXQNwFA
+qZgKBsk0jWcOSvI0bpK90km5flCHn/OA1rDCdaPuMwreDhvNDoApORYFPZVsLhid
+CXSqT+FWfm2NfegS+Q4VHP3YLbY4vLepCerU9aMTUIPit0kf1N8piG/l6AUno1XP
+VrcTvruQUWQb08H9aYt7l7kyhzOKkuXjVbdn5egZnK0m4WKmV50guA==
+-----END ATTRIBUTE CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa-expired.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa-expired.pem
new file mode 100644
index 0000000..20336fd
--- /dev/null
+++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa-expired.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDJzCCAg+gAwIBAgIIKiJDZY0XfQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
+Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDYwOTQ4NTJaFw0xNDAyMDcwOTQ4NTJaMD0x
+CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRMwEQYDVQQD
+EwpleHBpcmVkIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0s5R
+X2Y9KUSoNewtwOhQunET9VRGrVYS+xDewmIuAHZt4jhbETSHS+r/qipV4mI+/orS
+zma0+GVcDwbHRT3oDCrpG/DMpPznki+OzHT9e/HHk0yxb0Ti6vDDbZOM8y3r7ak0
+Dcq6BgGwPxwIW2u1YHRTj4yxlr5wj9iKU1SQGCwZIQZmjqrjoQlcrThIXju2bqN3
+SOjuaN6A2GAvcbb/IeQEm8HBqulmyBuGV7Gk9umG/nr61rulNxEp+3Dsce5mv7JR
+dX5W8P6pv38A/f31Bh/EetEkv8qdnkH0aVAvd8Kb2yxc8Ofdu0kJNoPHGjrnSywl
+kPh3z2pw6nOFpyFHoQIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2bbO1
+5eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAh9Sxryf5ip00ykCMStDYzQk27l4N
+ncjU19RJqjrCuHupvWPJ+aYQFvssAnGGuK2rbw3rzVQba/Vn/o5d5wr1gxRtNQjv
+z60jbqllmjF0TWvPf/CM/5LVAQJs2x5Mqtvy3pbNvetFHjZrzVDobdVJpqzaZGnh
+oP0+HUMdE+fyLa0LfaRKYNv7r/vxvzsHZvgJawHK1b/2VWtrkIMyhAgHYViih06j
+2bfVI/f5tk7/UljzLOCB22IFIn05wh4jyKq6az7B2Xu1Kk0/eA12eRqG134P8OYe
+hAPcuj4QEDwV0ESw5cueD2I0MxbXuH2vBG5ziSBfw2Phj7f9iYurmMsZew==
+-----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa.pem
new file mode 100644
index 0000000..fbfa7ee
--- /dev/null
+++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
+Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx
+CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD
+Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH
+hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP
+dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L
+lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/
+QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N
+jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2
+bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM
+ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik
+gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02
+R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA
+6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g
+91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ==
+-----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa-expired.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa-expired.pem
new file mode 100644
index 0000000..0e694c4
--- /dev/null
+++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa-expired.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA0s5RX2Y9KUSoNewtwOhQunET9VRGrVYS+xDewmIuAHZt4jhb
+ETSHS+r/qipV4mI+/orSzma0+GVcDwbHRT3oDCrpG/DMpPznki+OzHT9e/HHk0yx
+b0Ti6vDDbZOM8y3r7ak0Dcq6BgGwPxwIW2u1YHRTj4yxlr5wj9iKU1SQGCwZIQZm
+jqrjoQlcrThIXju2bqN3SOjuaN6A2GAvcbb/IeQEm8HBqulmyBuGV7Gk9umG/nr6
+1rulNxEp+3Dsce5mv7JRdX5W8P6pv38A/f31Bh/EetEkv8qdnkH0aVAvd8Kb2yxc
+8Ofdu0kJNoPHGjrnSywlkPh3z2pw6nOFpyFHoQIDAQABAoIBAQCRRwiDM2VhBGTc
+THi3oiLIaldz0fGnUVNhXR33XkwPm45cwbPY5pd7NWeecPChRE3fg/KFtfhv2wKX
+hHdd+6zofcYKsGeIKJa6gzXpJ5LtkRGWLNt3MEUl3mkAIhiYGoSmU96Axr5ul0lM
+JNiJkG/+GgzgN/jHR1UxfOzPQs7PKIyzCE2N0v8dRxHWeyPCRxSavlhAoQKjWxCe
+FfVBzLi+L1faidcwf4GWyeTfhvALXQnQGgVPH6PX0z3mwaeYHPWVXWJGcaF0bi3H
+HaEb2YexTDkEVU0PUVYO40OgtmKVLmi5t+ZP+/dFasy9elzgM3sSmVc7IBp6BBCH
+NgUcWcf1AoGBAOiti9raozwdA/wHAMaCCbgXq8Dg0+3LYnb0ob7w8OaHRl4Mvpup
+7MtxPGmr9IOddf8/49+L9STsioMllGt0TrkMrlKyg/eglGMalvbJmUYw1kERtQZw
+0CYYE8DXR3fvN+eMl1maZ4Wf048UugWQhsRGzOyUKcMXhAlIXwTevnCfAoGBAOfv
+isxrw5vttRxfszZaWeomos9bk6NA9FJYG1rS6ocR+Ww2OpQSJVTmbjpYv1lTb9yr
+PvcZtPbWP/6g8kjPTQQ+ZnJQB4RpWek0KlxwxC6JW5HzqMJFn68zX4/jE5kXqVow
+Y+Sfgrkr4QXX8vjzp9GFRhAW6bA5DlswqH7XmB+/AoGARHYDx3I7Q026RWZ+GOpc
+F7mHRKoiUT5di2ixSrA0AXBeCQAw+TZHQRjhUKpSuIMVG/RdhQH2MFYU7z+YawF+
+xD3x8M0rvSmXX42MS7LHkXp/IAgovmtlI0BEV6JAGg7d4Rhh0/B1c0Cyi8/qaAa9
+UHUQiK+Tlh6OL/kGVDWBzTsCgYBTW5Jk+e4pontPIU4FoN9j+lLVd7JOIFAvMB9U
+uy0zMlCUhcDz6rmkE9VV/wN2lThE9P8CTCjv9fy2BR5O8MJbXhnvx7eL7Vk1KVx4
+MMcxeoiAojPq7p7/ltUnn5MxmIFzOqUMTA/tgUm0kfJvaxLLiLyvl6yRe1AfkhNc
+0xuHfQKBgQCyQEcvtmR1Qx82ob5uTvBbKFDbSniiJMi9kgMk266PNRdg85Q4RC7X
+j5KNALOb5u2oMT6/Hzi4KruDBc/6viXRuMYM+L1JIy8y6wcVjCQetxyUIGgc9Ouh
+59bOkD+SOth52Y+AYFyCaJOSoTFHlTcLwCvk9gVdbgVYJi7/jyohSQ==
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa.pem
new file mode 100644
index 0000000..a4e0017
--- /dev/null
+++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF
+FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA
+Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY
+zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT
+jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf
++7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+
+eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz
+d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn
+DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB
+01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot
+mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK
+vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM
+lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH
+mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i
+xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf
+3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo
+vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/
+zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S
+Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ
+3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV
+oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+
+XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N
+GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV
+2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3
+RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4=
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/description.txt b/testing/tests/ikev2/shunt-policies-nat-rw/description.txt
new file mode 100644
index 0000000..7d9ebfd
--- /dev/null
+++ b/testing/tests/ikev2/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>type=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/ikev2/shunt-policies-nat-rw/evaltest.dat b/testing/tests/ikev2/shunt-policies-nat-rw/evaltest.dat
new file mode 100644
index 0000000..4d36673
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/evaltest.dat
@@ -0,0 +1,12 @@
+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
+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
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf
new file mode 100644
index 0000000..4c6e51d
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf
@@ -0,0 +1,27 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+
+conn nat-t
+	left=%any
+	leftcert=aliceCert.pem
+	leftid=alice at strongswan.org
+	leftsourceip=%config
+	right=PH_IP_SUN
+	rightid=@sun.strongswan.org
+	rightsubnet=0.0.0.0/0
+	auto=add
+
+conn local-net
+	leftsubnet=10.1.0.0/16
+	rightsubnet=10.1.0.0/16
+	authby=never
+	type=pass
+	auto=route
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
new file mode 100644
index 0000000..dabff38
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,7 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown
+
+  keep_alive = 5
+}
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf
new file mode 100644
index 0000000..90a8ae2
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf
@@ -0,0 +1,20 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+
+conn nat-t
+	left=PH_IP_SUN
+	leftcert=sunCert.pem
+	leftid=@sun.strongswan.org
+	leftfirewall=yes
+	leftsubnet=0.0.0.0/0
+	right=%any
+	rightsourceip=10.3.0.0/28
+	auto=add
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules
new file mode 100644
index 0000000..ae8f9a6
--- /dev/null
+++ b/testing/tests/ikev2/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/ikev2/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
new file mode 100644
index 0000000..ca23c69
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown
+}
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf
new file mode 100644
index 0000000..ade6415
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf
@@ -0,0 +1,27 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+
+conn nat-t
+	left=%any
+	leftcert=venusCert.pem
+	leftid=@venus.strongswan.org
+	leftsourceip=%config
+	right=PH_IP_SUN
+	rightid=@sun.strongswan.org
+	rightsubnet=0.0.0.0/0
+	auto=add
+
+conn local-net
+	leftsubnet=10.1.0.0/16
+	rightsubnet=10.1.0.0/16
+	authby=never
+	type=pass
+	auto=route
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
new file mode 100644
index 0000000..dabff38
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
@@ -0,0 +1,7 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown
+
+  keep_alive = 5
+}
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/posttest.dat b/testing/tests/ikev2/shunt-policies-nat-rw/posttest.dat
new file mode 100644
index 0000000..1ff2c06
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/posttest.dat
@@ -0,0 +1,5 @@
+sun::ipsec stop
+alice::ipsec stop
+venus::ipsec stop
+sun::iptables-restore < /etc/iptables.flush
+moon::iptables -t nat -F
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/pretest.dat b/testing/tests/ikev2/shunt-policies-nat-rw/pretest.dat
new file mode 100644
index 0000000..b96aa0c
--- /dev/null
+++ b/testing/tests/ikev2/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
+alice::ipsec start
+venus::ipsec start
+sun::ipsec start
+alice::expect-connection nat-t
+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
diff --git a/testing/tests/ikev2/shunt-policies-nat-rw/test.conf b/testing/tests/ikev2/shunt-policies-nat-rw/test.conf
new file mode 100644
index 0000000..bd82f03
--- /dev/null
+++ b/testing/tests/ikev2/shunt-policies-nat-rw/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 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"
diff --git a/testing/tests/ikev2/shunt-policies/description.txt b/testing/tests/ikev2/shunt-policies/description.txt
deleted file mode 100644
index dd78a5e..0000000
--- a/testing/tests/ikev2/shunt-policies/description.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-All traffic from the clients <b>alice</b> and <b>venus</b> is tunneled
-by default gateway <b>moon</b> to VPN gateway <b>sun</b>. In order to
-prevent local traffic within the <b>10.1.0.0/16</b> subnet to enter the
-tunnel, a <b>local-net</b> shunt policy with <b>type=pass</b> is set up.
-In order for the shunt to work, automatic route insertion must be disabled
-by adding <b>install_routes = no</b> to the charon section of <b>strongswan.conf</b>.
-<p/>
-In order to demonstrate the use of <b>type=drop</b> shunt policies, the
-<b>venus-icmp</b> connection prevents ICMP traffic to and from <b>venus</b>
-to use the IPsec tunnel by dropping such packets. Since this policy does not
-apply to the localnet, <b>venus</b> and <b>moon</b> can still ping each other.
diff --git a/testing/tests/ikev2/shunt-policies/evaltest.dat b/testing/tests/ikev2/shunt-policies/evaltest.dat
deleted file mode 100644
index a6e40a8..0000000
--- a/testing/tests/ikev2/shunt-policies/evaltest.dat
+++ /dev/null
@@ -1,16 +0,0 @@
-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
-alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
-alice::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-venus::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::NO
-venus::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-moon:: ping -c 1 -I PH_IP_MOON1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
-moon:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
-sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
-venus::ssh PH_IP_BOB hostname::bob::YES
-bob::  ssh PH_IP_VENUS hostname::venus::YES
diff --git a/testing/tests/ikev2/shunt-policies/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/shunt-policies/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 46ca4cd..0000000
--- a/testing/tests/ikev2/shunt-policies/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,40 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-	mobike=no
-
-conn local-net
-	leftsubnet=10.1.0.0/16
-	rightsubnet=10.1.0.0/16
-	authby=never
-	type=pass
-	auto=route
-
-conn venus-icmp
-	leftsubnet=PH_IP_VENUS/32
-	rightsubnet=0.0.0.0/0
-	leftprotoport=icmp
-	rightprotoport=icmp
-	leftauth=any
-	rightauth=any	
-	type=drop
-	auto=route
-
-conn net-net 
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftsubnet=10.1.0.0/16
-	leftfirewall=yes
-	lefthostaccess=yes
-	right=PH_IP_SUN
-	rightid=@sun.strongswan.org
-	rightsubnet=0.0.0.0/0
-	auto=add
diff --git a/testing/tests/ikev2/shunt-policies/hosts/moon/etc/iptables.rules b/testing/tests/ikev2/shunt-policies/hosts/moon/etc/iptables.rules
deleted file mode 100644
index af0f252..0000000
--- a/testing/tests/ikev2/shunt-policies/hosts/moon/etc/iptables.rules
+++ /dev/null
@@ -1,32 +0,0 @@
-*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 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
-
-# allow icmp in local net
--A INPUT  -i eth1 -p icmp -j ACCEPT
--A OUTPUT -o eth1 -p icmp -j ACCEPT
-
-COMMIT
diff --git a/testing/tests/ikev2/shunt-policies/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/shunt-policies/hosts/moon/etc/strongswan.conf
deleted file mode 100644
index a5cd14b..0000000
--- a/testing/tests/ikev2/shunt-policies/hosts/moon/etc/strongswan.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
-  multiple_authentication = no
-  install_routes = no
-}
diff --git a/testing/tests/ikev2/shunt-policies/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/shunt-policies/hosts/sun/etc/ipsec.conf
deleted file mode 100644
index cd8ea23..0000000
--- a/testing/tests/ikev2/shunt-policies/hosts/sun/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
-	mobike=no
-
-conn net-net 
-	left=PH_IP_SUN
-	leftcert=sunCert.pem
-	leftid=@sun.strongswan.org
-	leftsubnet=0.0.0.0/0
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/ikev2/shunt-policies/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/shunt-policies/hosts/sun/etc/strongswan.conf
deleted file mode 100644
index 8e685c8..0000000
--- a/testing/tests/ikev2/shunt-policies/hosts/sun/etc/strongswan.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
-  multiple_authentication = no
-}
diff --git a/testing/tests/ikev2/shunt-policies/posttest.dat b/testing/tests/ikev2/shunt-policies/posttest.dat
deleted file mode 100644
index 837738f..0000000
--- a/testing/tests/ikev2/shunt-policies/posttest.dat
+++ /dev/null
@@ -1,5 +0,0 @@
-moon::ipsec stop
-sun::ipsec stop
-moon::iptables-restore < /etc/iptables.flush
-sun::iptables-restore < /etc/iptables.flush
-
diff --git a/testing/tests/ikev2/shunt-policies/pretest.dat b/testing/tests/ikev2/shunt-policies/pretest.dat
deleted file mode 100644
index c724e5d..0000000
--- a/testing/tests/ikev2/shunt-policies/pretest.dat
+++ /dev/null
@@ -1,6 +0,0 @@
-moon::iptables-restore < /etc/iptables.rules
-sun::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-sun::ipsec start
-moon::sleep 1 
-moon::ipsec up net-net
diff --git a/testing/tests/ikev2/shunt-policies/test.conf b/testing/tests/ikev2/shunt-policies/test.conf
deleted file mode 100644
index 6b7432c..0000000
--- a/testing/tests/ikev2/shunt-policies/test.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/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-v-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"
diff --git a/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/certs/carolCert-002.pem b/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/certs/carolCert-002.pem
index 4ebebba..a4d9812 100644
--- a/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/certs/carolCert-002.pem
+++ b/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/certs/carolCert-002.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIEMDCCAxigAwIBAgIBFTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJDSDEZ
+MIIEMDCCAxigAwIBAgIBKTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
 MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
-b290IENBMB4XDTA5MDQwNzEyMDExN1oXDTE0MDQwNjEyMDExN1owaDELMAkGA1UE
+b290IENBMB4XDTE0MDQxNDIwNDY1NVoXDTE5MDQxMzIwNDY1NVowaDELMAkGA1UE
 BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAPBgNVBAsTCFJlc2Vh
 cmNoMQwwCgYDVQQFEwMwMDIxHTAbBgNVBAMUFGNhcm9sQHN0cm9uZ3N3YW4ub3Jn
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtXtFcjNbEEK76mVv1j3c
-6YWBeunBl7V9Qf1bPpzwTTUIKFDkg6HtWaNa7fxhTtHlPFHH8hdgiEZTQt626GoH
-8DKE1MaBOgvnW01vh2p1j8jW3VXSwBWBCM9vNnaxGic94Qiix6z+cAulCo1pzyY1
-XaJSGAvwG3Jap9/gChClAv65zg34mLWZpcXddUGoaOMu3JaRgVaNEiY4wGweMM3n
-hgxJ7+3q9vX+z5EqUQB59WBzVz7fU9FygLgfeAD1McrvMQOjo/PtkpEBOJipnjq9
-0k/+Z3gKIHbi6YIoIXDs7bOSaw8myvD5Bi4vNr5tKPr7bdLBU+AyAzRlJWV4GBw/
-rQIDAQABo4IBBjCCAQIwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwHQYDVR0OBBYE
-FABqD2vvGFgP2xX2Qqjx26Mz1RR5MG0GA1UdIwRmMGSAFF2n3XAGUTJ+57Zts7Xl
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzXQSXX8LtY/RlgvQxxCF
+pq787RPVD1HQciKemGkzUcjC+J+3rHBKmPT68Prb/4j9ESYdPqvaI7KWGD7pkAv4
+BWv4rw5iAxKB7bEDSVg5Gjs9vXDifR27Pz8rfsQFo8+O9oYWb7Ah45TNU/B8+Pcr
+Gajv0I7eHUbGJsKlgOOMBkSe3cbQd9jc54iv8AFFfMsh5riMz2+7LI8zaMzie3vN
+aPjsSDcGTB7jDa9bY+ZMbHzdFaDzmodDrZNJOSKTeDp5QTuP/JTPrSCXiIqUEJbE
+IUhWF2P1s8wH9SeW0ZQlw4Z0eETR/c7XQfzdJj7UCmWLJQ//eseoAXNc1DbV6EtJ
+1QIDAQABo4IBBjCCAQIwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwHQYDVR0OBBYE
+FGkt9dMYc1d/MRpfoo1q6zzwdBDMMG0GA1UdIwRmMGSAFF2n3XAGUTJ+57Zts7Xl
 4GDqLk3voUmkRzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25n
 U3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBSb290IENBggEAMB8GA1UdEQQYMBaB
 FGNhcm9sQHN0cm9uZ3N3YW4ub3JnMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9j
-cmwuc3Ryb25nc3dhbi5vcmcvc3Ryb25nc3dhbi5jcmwwDQYJKoZIhvcNAQEFBQAD
-ggEBAGuatpu8jxc22Iqglx5UIa8fkNSjfyLgO0RugCB+kPPilGttGWly+raLggQM
-Hu1qdt4l0cj60pe03Dc4GuUwJCW9J4ntVvCp1/SLcifvd3pMTtlrdSMpj105L5ma
-/nVksJ7UZPzcBLMq/8FtEg68H2WM+ixrmlm2cZiFDytMODEuAPCwWHOSP4WJNDzS
-KKc95ONxwTsD1VDm/ShcKw083XgvT7oHoei2RRDYp70CkatWOOJ7eMxdKdICl8nu
-9RlBLG8CJqcy7cJ4V7GOk6EOtGpGL/GR2gpLpvUnmWP9MUHYu8rVTzKQdW9A2Wjx
-fmSZH0LzbAm+7XFrP71rBSJUaUI=
+cmwuc3Ryb25nc3dhbi5vcmcvc3Ryb25nc3dhbi5jcmwwDQYJKoZIhvcNAQELBQAD
+ggEBAEbfq0PDdexYL9OqqD1Q8U0UXIRi3hvruqGM+KW8UbKisRqJJnow5wCYBJLI
+MFC7ze24AcADe0Az+uLdKzClVZ+87i/vMse0dCGxSvKKwUtI9bFeQOourrBEHHRw
+xJJcY9eGlsJoyJXyuT8sEXI+YqAaVDtcAYDa+OjIQNrJeIZDv9t/+1q1wlh0gvIz
+zfndSfL4xEIf+lw1Flvt8BwTx4jDk6QIS4jUO3YtHzrtZ+171/iqmSvGrEmfVceq
+1KOn7zNgh7XHmqE92HU63R9sVu3zjVSzuAMIVDqT5v8qU6T85NJE8ebYXi/RL8ON
+btGZ7+y4Z4CbdkjLZ+Oxtew0nwk=
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/private/carolKey-002.pem b/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/private/carolKey-002.pem
index aec8e7a..c1f4b17 100644
--- a/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/private/carolKey-002.pem
+++ b/testing/tests/ikev2/two-certs/hosts/carol/etc/ipsec.d/private/carolKey-002.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAtXtFcjNbEEK76mVv1j3c6YWBeunBl7V9Qf1bPpzwTTUIKFDk
-g6HtWaNa7fxhTtHlPFHH8hdgiEZTQt626GoH8DKE1MaBOgvnW01vh2p1j8jW3VXS
-wBWBCM9vNnaxGic94Qiix6z+cAulCo1pzyY1XaJSGAvwG3Jap9/gChClAv65zg34
-mLWZpcXddUGoaOMu3JaRgVaNEiY4wGweMM3nhgxJ7+3q9vX+z5EqUQB59WBzVz7f
-U9FygLgfeAD1McrvMQOjo/PtkpEBOJipnjq90k/+Z3gKIHbi6YIoIXDs7bOSaw8m
-yvD5Bi4vNr5tKPr7bdLBU+AyAzRlJWV4GBw/rQIDAQABAoIBAFekBUCGPobWw2sJ
-u32J+IIpgAL8mgoKkkfo80SEg6O1ZZAaqJBNBZNRSRs+0zs+L+b2U4m88lg9Jf5Y
-EZqhgd3kd7NNfaCrmPnFpoONzOI4ClNvG8y5VcwMaNezcAmCQ+bFxd6J04IGjZhP
-/HYWLJVgSybjtPt8OP1zJv2VVirgSb1rHOzI9j1CsaIl6m1gcXU2hA3A2/BIOd6Y
-UgCxJKu8G7NsmW14TSbJshcI1tUFOfbxFlAhmeAD57Kw6eC2GVwuBhghAYCNbpx0
-TYcQeTsBUjubna30K7+8lU1uiblKNLDqAzWynHz8xm1QEo0Z7txP9RRJUZDzlpmx
-u9iCMp0CgYEA6ZSexI3igJ68bdTOBwdbFtA9wqUTbYj6MULfUkFwqGLswLpNhhGv
-Y9X8YHUjcWEEoLXZb9QftmQc1R/nFCWC2slBBrKw9oERUUVYoczNpbkqJI1fjVfJ
-lNFgPXqQlRGIgSzSZr0CdBVs2VZKp19izQRQQI8d3ATD+Q4503dorgMCgYEAxuaC
-jow+vgcNt0DxlVWiV9rYGR7sDPJhdDyWgZ+yfaG0lVaX/81cEVxalUKTGHeHrhFs
-tIrZbRaIo9+XINzqCBNqfgauAZRFCvDv/BQPoGW+XKe+nH7DcC5PH8lcH6k1uGlq
-1KaRPymLRF8/PMmQ92o5Gk6H+Ah523hOJSv5BI8CgYBXH91cmUO8D/leyjqS+pZq
-WwA+Yw5tE+Omjjf4WXppBIUkmhkigeQ2y/FYFTlEKBjuzQWupaOyh4MNp9msdRVr
-ABhmJC7Hs3q/IqudpmOqhfeHLMhQU0dYYASSye21/JU7AXn1YljQ7dDs/DfaWETl
-Dc/VVMyhbZGfi0PccbS0+wKBgQC686+DjQ7sTnT16nUoiHUvXuP/uLDm+mvfdZOC
-AzkiHPw/4kS8i6oeJ1B9OzZHqRI+6uHiUSBNCQEmBuNmYD8ZmCZgjqa/lT3QKudn
-aPPHL9rd/E2NixjoOJ7mob2VhNaZn3xqpKWhWMsuWNh3qn44D//cWjQzTsQ7JblN
-9yb4wQKBgQCUs7wKhD/c45ST7bWH3C/iXBXsUwJrVPLKrCxl5vzkKTiDevMDVndo
-/jRAVk5UQEGO+R2eaqsgEujsS+ypGG1EWAdDyQ/6v8/34I7UF/bh5lZYOh1dXr6F
-PIROdfotGWYq2ituq1IbJMKFwhZLM7CRqnr0qsb9UaZeeuhqB3PAKQ==
+MIIEpAIBAAKCAQEAzXQSXX8LtY/RlgvQxxCFpq787RPVD1HQciKemGkzUcjC+J+3
+rHBKmPT68Prb/4j9ESYdPqvaI7KWGD7pkAv4BWv4rw5iAxKB7bEDSVg5Gjs9vXDi
+fR27Pz8rfsQFo8+O9oYWb7Ah45TNU/B8+PcrGajv0I7eHUbGJsKlgOOMBkSe3cbQ
+d9jc54iv8AFFfMsh5riMz2+7LI8zaMzie3vNaPjsSDcGTB7jDa9bY+ZMbHzdFaDz
+modDrZNJOSKTeDp5QTuP/JTPrSCXiIqUEJbEIUhWF2P1s8wH9SeW0ZQlw4Z0eETR
+/c7XQfzdJj7UCmWLJQ//eseoAXNc1DbV6EtJ1QIDAQABAoIBAQCiSRgkoDDolpSv
+199vDl7z3e9NeUfnlPF45l2t+BMge9t+NfMIk55pGcGKTi0uuM9lF10sXuStI+ip
+eDBXpwyfg7zo0gybbqgQz6zP548baEYJeLx+pdh9SfGabU4jKdU8Z4gbat4p/ST/
+M8wTgHGcEDR14hQSvg/RGBlRKOw3Gdq5+lWWHePfL0Lx7xmvXDcrOxtgN3aaQaHB
+b6bcb6V6vxcXeQR5eLV1k5mHFauu0wunFOimJrzozBfaUmlsOCGI1t9+3F0HPH9U
+SL4CHDQkzb8owE+3PNDAFKlads7/3dkp5bS2YeWNwYUvCLcima2isyH7eQa033Aw
+LK+XvgBhAoGBAP55aQGGmuXbdRvOa7YwobQHaUppV/ZLPSQlrmbeTCVv4SN0OmvT
+DQh+VjlQ0+XhJudhIGRTdVns7xi5BWy1H2dPvOOG0VX5xVLyEVcyOfAmII8zP3Mo
+ZzzShehwfi7Pu4hlGwt/oaFuIID9nNROJ8wxF0KsHaTnJvJIAP9GEu0dAoGBAM6v
+a4OGeNkWrGfSJ1PQXkV3r49Uib4n8ToWbAmbKn5lf+Hq25+3p94ontm7cj7NSq6q
+iOYPrnG/r9of+ikCU+065RpI/Xf91Yf3uy5YXY8GUTumknXCI8nXE4Nt42HrW1pB
+hoFh/Z4dSs6jX8G3LuJiPdvQ3Bi5SsOiEaFruwoZAoGADMFfLxFlMEJY02T8Zyx2
+3oREldND8neBAA/XdxaLcJD0EwffacoxbAyRG9xeUrZ/cbefnQfF6RUEQxP7HqDR
+iycnC6yVT57uciLqFZnR56SxmxvxgT80NYtD5QvGd2g4OTUALwpduq6/eFe+BbJJ
+MmX/iXsBHWPswtYzHpiPmE0CgYAy+gkmc3Ay+uii4q5YebgGojJmw48Fm4xfq1AS
+PncInbgg3HA2wHFi1dn4EcdnvfKBigYh2BRKceDJh8GHg893X2NKTF5Xzf9wfaVp
+FNpegExgzgCpkqyJB8cET4IZkJcDd83Y83Y+HTNqK9leSfQCWgCvyp++aVULU1nN
+2mhTYQKBgQD7MvZ4zXOHCqWQpYyKAMxAo+0xoZcT6LCNYRfkehwYQRRtVSH74S0Z
+npadWcLXCuIJULgPD/JxCqHBylEoRjFC6BYmqTJJva7mLkf9es09kS7MPmNxGs60
+S0Wg4PBCXe74uN7+IgziCoSBGiUxTg36B687+PesvhhCnsTLFYbYZA==
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/certs/moonCert.asc b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/certs/moonCert.asc
new file mode 100644
index 0000000..135cfae
--- /dev/null
+++ b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/certs/moonCert.asc
@@ -0,0 +1,15 @@
+Type Bits/KeyID    Date       User ID
+pub  1024/613A3B61 2005/08/07 moon <moon.strongswan.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 2.6.3i
+
+mQCNA0L2KI8AAAEEAM5GYrwuf1M9Cv7+Yfr6i5+17zMVGIyj/D4+msK43iUbEH61
++bhRKcrF+9NKvM+ujjZoUbfGjUipsBbTlPTaY7muZ9KaVy2OBHm73x13eiemkPS9
+RFWesrL9L39aBO5K47ti0PwRP8QIPMaNWMs2z7yoZLE/flVNQfWsCnlhOjthAAUR
+tBptb29uIDxtb29uLnN0cm9uZ3N3YW4ub3JnPokAlQMFEEL2KI/1rAp5YTo7YQEB
+vX4EAKtr0e6WMDIRlpE4VhhdQ7AgBgGyhgfqAdD9KDx8o4fG4nkmh7H1bG/PLJA1
+f+UfDGnOyIwPOrILNyNnwAbDHXjJaNylahM7poOP7i0VlbhZPLAC0cSQi02/Zrac
+t5bED5tHSrNSjcA/CjuxRuu9lmR6s57IQnQnwt9I4LTM+CFP
+=oaBj
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/certs/sunCert.asc b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/certs/sunCert.asc
new file mode 100644
index 0000000..32f204b
--- /dev/null
+++ b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/certs/sunCert.asc
@@ -0,0 +1,15 @@
+Type Bits/KeyID    Date       User ID
+pub  1024/79949ADD 2005/08/07 sun <sun.strongswan.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 2.6.3i
+
+mQCNA0L2Km8AAAEEANRAVMn8HBxfYaGhLqtQ3IZJArn9wpcQ+7sH/F9PaXIjzHRQ
+rfFkfmxxp9lVjCk0LM/BnnlnUmyz6F8K7V0Gi40Am4+ln1zHvZZIQJYGrDhDnjb7
+I5TVeD4Ib5bQ1CoUbIhv2LocCeR6OjefQgGmerC5RQ3d5ci7uB0pVpd5lJrdAAUR
+tBhzdW4gPHN1bi5zdHJvbmdzd2FuLm9yZz6JAJUDBRBC9ipvHSlWl3mUmt0BAUZR
+A/43nuZbxADMSviu54Mj8pvQbYeGLQVabiWT6h7L0ZPX4MWpFH3dTixBfRrZRSsj
+0AgiMMuZAMebfOe+Xf9uDQv7p1yumEiNg43tg85zyawkARWNTZZ04woxtvAqNwXn
+lQotGz7YA6JMxry9RQo5yI4Y4dPnVZ/o8eDpP0+I88cOhQ==
+=lLvB
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/private/moonKey.asc b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/private/moonKey.asc
new file mode 100644
index 0000000..6524773
--- /dev/null
+++ b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/moon/etc/ipsec.d/private/moonKey.asc
@@ -0,0 +1,19 @@
+Type Bits/KeyID    Date       User ID
+sec  1024/613A3B61 2005/08/07 moon <moon.strongswan.org>
+
+-----BEGIN PGP SECRET KEY BLOCK-----
+Version: 2.6.3i
+
+lQHYA0L2KI8AAAEEAM5GYrwuf1M9Cv7+Yfr6i5+17zMVGIyj/D4+msK43iUbEH61
++bhRKcrF+9NKvM+ujjZoUbfGjUipsBbTlPTaY7muZ9KaVy2OBHm73x13eiemkPS9
+RFWesrL9L39aBO5K47ti0PwRP8QIPMaNWMs2z7yoZLE/flVNQfWsCnlhOjthAAUR
+AAP9Fj7OaaCfTL3Met8yuS8ZGMDL/fq+4f2bM+OdPSgD4N1Fiye0B1QMCVGWI1Xd
+JXS0+9QI0A3iD12YAnYwsP50KmsLHA69AqchN7BuimoMfHDXqpTSRW57E9MCEzQ9
+FFN8mVPRiDxAUro8qCjdHmk1vmtdt/PXn1BuXHE36SzZmmMCANBA4WHaO6MJshM6
+7StRicSCxoMn/lPcj6rfJS4EaS+a0MwECxKQ3HKTpP3/+7kaWfLI/D65Xmi3cVK3
+0CPwUK8CAP2RYWoBZPSA8dBGFYwR7W6bdNYhdmGmsVCaM7v4sVr0FwHwMERadByN
+8v0n5As3ZbrCURRp68wuE+JjfOM5mO8CAM3ZK7AVlBOqkoI3X3Ji3yviLlsr2ET7
+QrVKFQBq7eUhwYFo6mVemEqQb61tGirq+qL4Wfk/7+FffZPsUyLX1amfjLQabW9v
+biA8bW9vbi5zdHJvbmdzd2FuLm9yZz4=
+=YFQm
+-----END PGP SECRET KEY BLOCK-----
diff --git a/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/certs/moonCert.asc b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/certs/moonCert.asc
new file mode 100644
index 0000000..135cfae
--- /dev/null
+++ b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/certs/moonCert.asc
@@ -0,0 +1,15 @@
+Type Bits/KeyID    Date       User ID
+pub  1024/613A3B61 2005/08/07 moon <moon.strongswan.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 2.6.3i
+
+mQCNA0L2KI8AAAEEAM5GYrwuf1M9Cv7+Yfr6i5+17zMVGIyj/D4+msK43iUbEH61
++bhRKcrF+9NKvM+ujjZoUbfGjUipsBbTlPTaY7muZ9KaVy2OBHm73x13eiemkPS9
+RFWesrL9L39aBO5K47ti0PwRP8QIPMaNWMs2z7yoZLE/flVNQfWsCnlhOjthAAUR
+tBptb29uIDxtb29uLnN0cm9uZ3N3YW4ub3JnPokAlQMFEEL2KI/1rAp5YTo7YQEB
+vX4EAKtr0e6WMDIRlpE4VhhdQ7AgBgGyhgfqAdD9KDx8o4fG4nkmh7H1bG/PLJA1
+f+UfDGnOyIwPOrILNyNnwAbDHXjJaNylahM7poOP7i0VlbhZPLAC0cSQi02/Zrac
+t5bED5tHSrNSjcA/CjuxRuu9lmR6s57IQnQnwt9I4LTM+CFP
+=oaBj
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/certs/sunCert.asc b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/certs/sunCert.asc
new file mode 100644
index 0000000..32f204b
--- /dev/null
+++ b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/certs/sunCert.asc
@@ -0,0 +1,15 @@
+Type Bits/KeyID    Date       User ID
+pub  1024/79949ADD 2005/08/07 sun <sun.strongswan.org>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: 2.6.3i
+
+mQCNA0L2Km8AAAEEANRAVMn8HBxfYaGhLqtQ3IZJArn9wpcQ+7sH/F9PaXIjzHRQ
+rfFkfmxxp9lVjCk0LM/BnnlnUmyz6F8K7V0Gi40Am4+ln1zHvZZIQJYGrDhDnjb7
+I5TVeD4Ib5bQ1CoUbIhv2LocCeR6OjefQgGmerC5RQ3d5ci7uB0pVpd5lJrdAAUR
+tBhzdW4gPHN1bi5zdHJvbmdzd2FuLm9yZz6JAJUDBRBC9ipvHSlWl3mUmt0BAUZR
+A/43nuZbxADMSviu54Mj8pvQbYeGLQVabiWT6h7L0ZPX4MWpFH3dTixBfRrZRSsj
+0AgiMMuZAMebfOe+Xf9uDQv7p1yumEiNg43tg85zyawkARWNTZZ04woxtvAqNwXn
+lQotGz7YA6JMxry9RQo5yI4Y4dPnVZ/o8eDpP0+I88cOhQ==
+=lLvB
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/private/sunKey.asc b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/private/sunKey.asc
new file mode 100644
index 0000000..de23936
--- /dev/null
+++ b/testing/tests/openssl-ikev2/net2net-pgp-v3/hosts/sun/etc/ipsec.d/private/sunKey.asc
@@ -0,0 +1,19 @@
+Type Bits/KeyID    Date       User ID
+sec  1024/79949ADD 2005/08/07 sun <sun.strongswan.org>
+
+-----BEGIN PGP SECRET KEY BLOCK-----
+Version: 2.6.3i
+
+lQHYA0L2Km8AAAEEANRAVMn8HBxfYaGhLqtQ3IZJArn9wpcQ+7sH/F9PaXIjzHRQ
+rfFkfmxxp9lVjCk0LM/BnnlnUmyz6F8K7V0Gi40Am4+ln1zHvZZIQJYGrDhDnjb7
+I5TVeD4Ib5bQ1CoUbIhv2LocCeR6OjefQgGmerC5RQ3d5ci7uB0pVpd5lJrdAAUR
+AAP8DHxBOQ7UeiO6cutdGSLfy6nxGf/eRR8d3dNLFKpRfy9IQxPN/yQHb8pzSQUI
+Pqi3V4PcJUJQJIMNqzzgyTyey/OdTc+IFngywRGKQowyD7vY+urVbcEDHe+sRTL1
+GvrsQGMZoXNDimABHn5NbT6Pc06xQ9rNvpCSyHMyzcylpk0CANqf96aEaryGJozg
+vSN5GlS77rPJ9Y9mU2EJs1+0BlMcb7Sy4HN2RRc/V56ZmlW2m3UbGwPqG8R9XQQ2
+LO03bTcCAPiJbTcRdA/YnZExbZPgEnV5nq8tVXTc7bz1Sw7ZWRef0iZyIQEXbwLn
+2Z2EJik9bQpkcVJSBV17cH7Av/VdIosCAKJPVoBETiVzWejIpGHHqbnmZC8P9rUs
+xAXZbNukbL3YElLeopNMyddTi6kf45/m0sb7fr7rzW/OJ7WP8mDrGPec4rQYc3Vu
+IDxzdW4uc3Ryb25nc3dhbi5vcmc+
+=DwEu
+-----END PGP SECRET KEY BLOCK-----
diff --git a/testing/tests/pfkey/compress/description.txt b/testing/tests/pfkey/compress/description.txt
new file mode 100644
index 0000000..4c60384
--- /dev/null
+++ b/testing/tests/pfkey/compress/description.txt
@@ -0,0 +1,4 @@
+This scenario enables IPComp compression between roadwarrior <b>carol</b> and
+gateway <b>moon</b>. Two pings from <b>carol</b> to <b>alice</b> check
+the established tunnel with compression. The packet sizes of the two pings
+are different because the kernel does not compress small packets.
diff --git a/testing/tests/pfkey/compress/evaltest.dat b/testing/tests/pfkey/compress/evaltest.dat
new file mode 100644
index 0000000..843326e
--- /dev/null
+++ b/testing/tests/pfkey/compress/evaltest.dat
@@ -0,0 +1,12 @@
+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
+carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL.*IPCOMP::YES
+moon:: ipsec status 2> /dev/null::rw.*INSTALLED, TUNNEL.*IPCOMP::YES
+moon:: cat /var/log/daemon.log::IKE_AUTH request.*N(IPCOMP_SUP)::YES
+moon:: cat /var/log/daemon.log::IKE_AUTH response.*N(IPCOMP_SUP)::YES
+moon:: ip xfrm state::proto comp spi::YES
+carol::ip xfrm state::proto comp spi::YES
+carol::ping -n -c 1 -s 8184 -p deadbeef PH_IP_ALICE::8192 bytes from PH_IP_ALICE::YES
+carol::ping -n -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE::YES
+moon::tcpdump::carol.strongswan.org > moon.strongswan.org: ESP::YES
+moon::tcpdump::moon.strongswan.org >  carol.strongswan.org: ESP::YES
diff --git a/testing/tests/pfkey/compress/hosts/carol/etc/ipsec.conf b/testing/tests/pfkey/compress/hosts/carol/etc/ipsec.conf
new file mode 100644
index 0000000..7880989
--- /dev/null
+++ b/testing/tests/pfkey/compress/hosts/carol/etc/ipsec.conf
@@ -0,0 +1,21 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+	compress=yes
+	leftfirewall=yes
+
+conn home
+	left=PH_IP_CAROL
+	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/pfkey/compress/hosts/carol/etc/strongswan.conf b/testing/tests/pfkey/compress/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..2061e52
--- /dev/null
+++ b/testing/tests/pfkey/compress/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-pfkey kernel-netlink socket-default updown
+}
diff --git a/testing/tests/pfkey/compress/hosts/moon/etc/ipsec.conf b/testing/tests/pfkey/compress/hosts/moon/etc/ipsec.conf
new file mode 100644
index 0000000..718b3c8
--- /dev/null
+++ b/testing/tests/pfkey/compress/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,21 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+	compress=yes
+	leftfirewall=yes
+
+conn rw
+	left=PH_IP_MOON
+	leftcert=moonCert.pem
+	leftid=@moon.strongswan.org
+	leftsubnet=10.1.0.0/16
+	right=%any
+	rightid=carol at strongswan.org
+	auto=add
diff --git a/testing/tests/pfkey/compress/hosts/moon/etc/strongswan.conf b/testing/tests/pfkey/compress/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..2061e52
--- /dev/null
+++ b/testing/tests/pfkey/compress/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-pfkey kernel-netlink socket-default updown
+}
diff --git a/testing/tests/pfkey/compress/posttest.dat b/testing/tests/pfkey/compress/posttest.dat
new file mode 100644
index 0000000..046d4cf
--- /dev/null
+++ b/testing/tests/pfkey/compress/posttest.dat
@@ -0,0 +1,4 @@
+moon::ipsec stop
+carol::ipsec stop
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
diff --git a/testing/tests/pfkey/compress/pretest.dat b/testing/tests/pfkey/compress/pretest.dat
new file mode 100644
index 0000000..29a9035
--- /dev/null
+++ b/testing/tests/pfkey/compress/pretest.dat
@@ -0,0 +1,6 @@
+carol::iptables-restore < /etc/iptables.rules
+moon::iptables-restore < /etc/iptables.rules
+carol::ipsec start
+moon::ipsec start
+carol::sleep 2
+carol::ipsec up home
diff --git a/testing/tests/pfkey/compress/test.conf b/testing/tests/pfkey/compress/test.conf
new file mode 100644
index 0000000..d7b7142
--- /dev/null
+++ b/testing/tests/pfkey/compress/test.conf
@@ -0,0 +1,22 @@
+#!/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"
+
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/description.txt b/testing/tests/pfkey/shunt-policies-nat-rw/description.txt
new file mode 100644
index 0000000..7d9ebfd
--- /dev/null
+++ b/testing/tests/pfkey/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>type=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/pfkey/shunt-policies-nat-rw/evaltest.dat b/testing/tests/pfkey/shunt-policies-nat-rw/evaltest.dat
new file mode 100644
index 0000000..4d36673
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/evaltest.dat
@@ -0,0 +1,12 @@
+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
+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
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf
new file mode 100644
index 0000000..4c6e51d
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf
@@ -0,0 +1,27 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+
+conn nat-t
+	left=%any
+	leftcert=aliceCert.pem
+	leftid=alice at strongswan.org
+	leftsourceip=%config
+	right=PH_IP_SUN
+	rightid=@sun.strongswan.org
+	rightsubnet=0.0.0.0/0
+	auto=add
+
+conn local-net
+	leftsubnet=10.1.0.0/16
+	rightsubnet=10.1.0.0/16
+	authby=never
+	type=pass
+	auto=route
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
new file mode 100644
index 0000000..7e96bf1
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,7 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-pfkey kernel-netlink socket-default updown
+
+  keep_alive = 5
+}
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf
new file mode 100644
index 0000000..90a8ae2
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf
@@ -0,0 +1,20 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+
+conn nat-t
+	left=PH_IP_SUN
+	leftcert=sunCert.pem
+	leftid=@sun.strongswan.org
+	leftfirewall=yes
+	leftsubnet=0.0.0.0/0
+	right=%any
+	rightsourceip=10.3.0.0/28
+	auto=add
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules
new file mode 100644
index 0000000..ae8f9a6
--- /dev/null
+++ b/testing/tests/pfkey/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/pfkey/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
new file mode 100644
index 0000000..c0f605d
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-pfkey kernel-netlink socket-default updown
+}
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf
new file mode 100644
index 0000000..ade6415
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf
@@ -0,0 +1,27 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+	keyexchange=ikev2
+
+conn nat-t
+	left=%any
+	leftcert=venusCert.pem
+	leftid=@venus.strongswan.org
+	leftsourceip=%config
+	right=PH_IP_SUN
+	rightid=@sun.strongswan.org
+	rightsubnet=0.0.0.0/0
+	auto=add
+
+conn local-net
+	leftsubnet=10.1.0.0/16
+	rightsubnet=10.1.0.0/16
+	authby=never
+	type=pass
+	auto=route
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
new file mode 100644
index 0000000..7e96bf1
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
@@ -0,0 +1,7 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-pfkey kernel-netlink socket-default updown
+
+  keep_alive = 5
+}
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/posttest.dat b/testing/tests/pfkey/shunt-policies-nat-rw/posttest.dat
new file mode 100644
index 0000000..1ff2c06
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/posttest.dat
@@ -0,0 +1,5 @@
+sun::ipsec stop
+alice::ipsec stop
+venus::ipsec stop
+sun::iptables-restore < /etc/iptables.flush
+moon::iptables -t nat -F
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/pretest.dat b/testing/tests/pfkey/shunt-policies-nat-rw/pretest.dat
new file mode 100644
index 0000000..b96aa0c
--- /dev/null
+++ b/testing/tests/pfkey/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
+alice::ipsec start
+venus::ipsec start
+sun::ipsec start
+alice::expect-connection nat-t
+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
diff --git a/testing/tests/pfkey/shunt-policies-nat-rw/test.conf b/testing/tests/pfkey/shunt-policies-nat-rw/test.conf
new file mode 100644
index 0000000..bd82f03
--- /dev/null
+++ b/testing/tests/pfkey/shunt-policies-nat-rw/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 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"
diff --git a/testing/tests/pfkey/shunt-policies/description.txt b/testing/tests/pfkey/shunt-policies/description.txt
deleted file mode 100644
index ad98eb8..0000000
--- a/testing/tests/pfkey/shunt-policies/description.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-All traffic from the clients <b>alice</b> and <b>venus</b> is tunneled
-by default gateway <b>moon</b> to VPN gateway <b>sun</b>. In order to
-prevent local traffic within the <b>10.1.0.0/16</b> subnet to enter the
-tunnel, a <b>local-net</b> shunt policy with <b>type=pass</b> is set up.
-In order for the shunt to work, automatic route insertion must be disabled
-by adding <b>install_routes = no</b> to the charon section of <b>strongswan.conf</b>.
-<p/>
-In order to demonstrate the use of <b>type=drop</b> shunt policies, the
-<b>venus-icmp</b> connection prevents ICMP traffic to and from <b>venus</b>
-to use the IPsec tunnel by dropping such packets. Since this policy does not
-apply to the local net, <b>venus</b> and <b>moon</b> can still ping each other.
diff --git a/testing/tests/pfkey/shunt-policies/evaltest.dat b/testing/tests/pfkey/shunt-policies/evaltest.dat
deleted file mode 100644
index 6ba3a98..0000000
--- a/testing/tests/pfkey/shunt-policies/evaltest.dat
+++ /dev/null
@@ -1,20 +0,0 @@
-moon:: ipsec status 2> /dev/null::local-net.*PASS::YES
-moon:: ipsec status 2> /dev/null::venus-icmp.*DROP::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-net.*INSTALLED, TUNNEL::YES
-sun::  ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
-alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
-alice::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-venus::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::NO
-venus::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-moon:: ping -c 1 -I PH_IP_MOON1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
-moon:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
-sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
-venus::ssh PH_IP_BOB hostname::bob::YES
-bob::ssh PH_IP_VENUS hostname::venus::YES
diff --git a/testing/tests/pfkey/shunt-policies/hosts/moon/etc/ipsec.conf b/testing/tests/pfkey/shunt-policies/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index 90a5d61..0000000
--- a/testing/tests/pfkey/shunt-policies/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,40 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-conn %default
-	ikelifetime=60m
-	keylife=20m
-	rekeymargin=3m
-	keyingtries=1
-	keyexchange=ikev2
-	mobike=no
-
-conn local-net
-	leftsubnet=10.1.0.0/16
-	rightsubnet=10.1.0.0/16
-	authby=never
-	type=pass
-	auto=route
-
-conn venus-icmp
-	leftsubnet=10.1.0.20/32
-	rightsubnet=0.0.0.0/0
-	leftprotoport=icmp
-	rightprotoport=icmp
-	leftauth=any
-	rightauth=any	
-	type=drop
-	auto=route
-
-conn net-net 
-	left=PH_IP_MOON
-	leftcert=moonCert.pem
-	leftid=@moon.strongswan.org
-	leftsubnet=10.1.0.0/16
-	leftfirewall=yes
-	lefthostaccess=yes
-	right=PH_IP_SUN
-	rightid=@sun.strongswan.org
-	rightsubnet=0.0.0.0/0
-	auto=add
diff --git a/testing/tests/pfkey/shunt-policies/hosts/moon/etc/iptables.rules b/testing/tests/pfkey/shunt-policies/hosts/moon/etc/iptables.rules
deleted file mode 100644
index af0f252..0000000
--- a/testing/tests/pfkey/shunt-policies/hosts/moon/etc/iptables.rules
+++ /dev/null
@@ -1,32 +0,0 @@
-*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 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
-
-# allow icmp in local net
--A INPUT  -i eth1 -p icmp -j ACCEPT
--A OUTPUT -o eth1 -p icmp -j ACCEPT
-
-COMMIT
diff --git a/testing/tests/pfkey/shunt-policies/hosts/moon/etc/strongswan.conf b/testing/tests/pfkey/shunt-policies/hosts/moon/etc/strongswan.conf
deleted file mode 100644
index 4582e14..0000000
--- a/testing/tests/pfkey/shunt-policies/hosts/moon/etc/strongswan.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-pfkey kernel-netlink socket-default updown
-  multiple_authentication = no
-  install_routes = no
-}
diff --git a/testing/tests/pfkey/shunt-policies/hosts/sun/etc/ipsec.conf b/testing/tests/pfkey/shunt-policies/hosts/sun/etc/ipsec.conf
deleted file mode 100644
index cd8ea23..0000000
--- a/testing/tests/pfkey/shunt-policies/hosts/sun/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
-	mobike=no
-
-conn net-net 
-	left=PH_IP_SUN
-	leftcert=sunCert.pem
-	leftid=@sun.strongswan.org
-	leftsubnet=0.0.0.0/0
-	leftfirewall=yes
-	right=PH_IP_MOON
-	rightid=@moon.strongswan.org
-	rightsubnet=10.1.0.0/16
-	auto=add
diff --git a/testing/tests/pfkey/shunt-policies/hosts/sun/etc/strongswan.conf b/testing/tests/pfkey/shunt-policies/hosts/sun/etc/strongswan.conf
deleted file mode 100644
index 902d83c..0000000
--- a/testing/tests/pfkey/shunt-policies/hosts/sun/etc/strongswan.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-pfkey kernel-netlink socket-default updown
-  multiple_authentication = no
-}
diff --git a/testing/tests/pfkey/shunt-policies/posttest.dat b/testing/tests/pfkey/shunt-policies/posttest.dat
deleted file mode 100644
index 837738f..0000000
--- a/testing/tests/pfkey/shunt-policies/posttest.dat
+++ /dev/null
@@ -1,5 +0,0 @@
-moon::ipsec stop
-sun::ipsec stop
-moon::iptables-restore < /etc/iptables.flush
-sun::iptables-restore < /etc/iptables.flush
-
diff --git a/testing/tests/pfkey/shunt-policies/pretest.dat b/testing/tests/pfkey/shunt-policies/pretest.dat
deleted file mode 100644
index c724e5d..0000000
--- a/testing/tests/pfkey/shunt-policies/pretest.dat
+++ /dev/null
@@ -1,6 +0,0 @@
-moon::iptables-restore < /etc/iptables.rules
-sun::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-sun::ipsec start
-moon::sleep 1 
-moon::ipsec up net-net
diff --git a/testing/tests/pfkey/shunt-policies/test.conf b/testing/tests/pfkey/shunt-policies/test.conf
deleted file mode 100644
index 6b7432c..0000000
--- a/testing/tests/pfkey/shunt-policies/test.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/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-v-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"
diff --git a/testing/tests/sql/shunt-policies-nat-rw/description.txt b/testing/tests/sql/shunt-policies-nat-rw/description.txt
new file mode 100644
index 0000000..7d9ebfd
--- /dev/null
+++ b/testing/tests/sql/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>type=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/sql/shunt-policies-nat-rw/evaltest.dat b/testing/tests/sql/shunt-policies-nat-rw/evaltest.dat
new file mode 100644
index 0000000..4d36673
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/evaltest.dat
@@ -0,0 +1,12 @@
+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
+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
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
new file mode 100644
index 0000000..50eccad
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.conf
@@ -0,0 +1,3 @@
+# /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.d/data.sql b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.d/data.sql
new file mode 100644
index 0000000..b1f5c7d
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.d/data.sql
@@ -0,0 +1,199 @@
+/* Identities */
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
+  9, X'3045310B300906035504061302434831193017060355040A13104C696E7578207374726F6E675377616E311B3019060355040313127374726F6E675377616E20526F6F74204341'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
+  11, X'5da7dd700651327ee7b66db3b5e5e060ea2e4def'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* keyid of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
+  11, X'ae096b87b44886d3b820978623dabd0eae22ebbc'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* alice at strongswan.org */
+  3, X'616c696365407374726f6e677377616e2e6f7267'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* sun.strongswan.org */
+  2, X'73756e2e7374726f6e677377616e2e6f7267'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, OU=Sales, CN=alice at strongswan.org' */
+  11, X'05da04208c02f428470acf6c772d066613da863c'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* %any */
+  0, '%any'
+);
+
+/* Certificates */
+
+INSERT INTO certificates (
+   type, keytype, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
+  1, 1, X'308203b53082029da003020102020100300d06092a864886f70d01010405003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3034303931303131303134355a170d3134303930383131303134355a3045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f7420434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bff25f [...]
+);
+
+INSERT INTO certificates (
+   type, keytype, data
+) VALUES ( /* C=CH, O=Linux strongSwan, OU=Sales, CN=alice at strongswan.org */
+  1, 1, X'3082041f30820307a003020102020119300d06092a864886f70d01010b05003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3039303832373130303732345a170d3134303832363130303732345a3057310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c6573311d301b06035504031414616c696365407374726f6e677377616e2e6f726730820122300d06092a864886f70d01010105 [...]
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 1
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 2
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 3
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  2, 4
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  2, 6
+);
+
+/* Private Keys */
+
+INSERT INTO private_keys (
+   type, data
+) VALUES ( /* key of 'C=CH, O=Linux strongSwan, OU=Sales, CN=alice at strongswan.org' */
+  1, X'308204a40201000282010100d88d6a4811e6972dd0daa2adf3c911bf5edd8664607bea67f45427a11af59184f0ab90c46007b8b5aa69fff71ab2ff2d822cd5f4c9ec94cd32ef8f49e73c91ff48e40c48b4fcdbfae4b023d857431865349f15f998ecf50dc65ffe7dc12dc37071788bc6fcf08fdfeda2c6c073a84724ff5193d73c622b1d2f545a1ff9d3ffd0fc62eb7a2be85bae427e3ee8362df0313630641e4cc8f639abd311718c843dad0634cd06cf361f204910cfc9ee48bfea590ae62e6952e8ab70e4bdc75ec51a2a29c6b74c48ee32c65a1e32b27ae330dc4acd1b762c84ea48fb684d3476241e9ae7feb9e38981d [...]
+);
+
+INSERT INTO private_key_identity (
+  private_key, identity
+) VALUES (
+  1, 4
+);
+
+INSERT INTO private_key_identity (
+  private_key, identity
+) VALUES (
+  1, 6
+);
+
+/* Configurations */
+
+INSERT INTO ike_configs (
+  local, remote
+) VALUES (
+  'PH_IP_ALICE', 'PH_IP_SUN'
+);
+
+INSERT INTO ike_configs (
+  local, remote
+) VALUES (
+  '%any', '%any'
+);
+
+INSERT INTO peer_configs (
+  name, ike_cfg, local_id, remote_id, virtual
+) VALUES (
+  'nat-t', 1, 4, 5, '0.0.0.0'
+);
+
+INSERT INTO peer_configs (
+  name, ike_cfg, local_id, remote_id, auth_method
+) VALUES (
+  'shunts', 2, 7, 7, 0
+);
+
+INSERT INTO child_configs (
+  name
+) VALUES (
+  'nat-t'
+);
+
+INSERT INTO child_configs (
+  name, mode, start_action
+) VALUES (
+  'local-net', 4, 1
+);
+
+INSERT INTO peer_config_child_config (
+  peer_cfg, child_cfg
+) VALUES (
+  1, 1
+);
+
+INSERT INTO peer_config_child_config (
+  peer_cfg, child_cfg
+) VALUES (
+  2, 2
+);
+
+INSERT INTO traffic_selectors (
+  type, start_addr, end_addr
+) VALUES ( /* 10.1.0.0/16 */
+  7, X'0a010000', X'0a01ffff'
+);
+
+INSERT INTO traffic_selectors (
+  type, start_addr, end_addr
+) VALUES ( /* 0.0.0.0/0 */
+  7, X'00000000', X'ffffffff'
+);
+
+INSERT INTO traffic_selectors (
+  type
+) VALUES ( /* dynamic/32 */
+  7
+);
+
+INSERT INTO child_config_traffic_selector (
+  child_cfg, traffic_selector, kind
+) VALUES (
+  1, 2, 1
+);
+
+INSERT INTO child_config_traffic_selector (
+	child_cfg, traffic_selector, kind
+) VALUES (
+  1, 3, 2
+);
+
+INSERT INTO child_config_traffic_selector (
+	child_cfg, traffic_selector, kind
+) VALUES (
+  2, 1, 0
+);
+
+INSERT INTO child_config_traffic_selector (
+	child_cfg, traffic_selector, kind
+) VALUES (
+  2, 1, 1
+);
diff --git a/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.secrets b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.secrets
similarity index 100%
copy from testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.secrets
copy to testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/ipsec.secrets
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
new file mode 100644
index 0000000..2f01cdc
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,12 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  plugins {
+    sql {
+      database = sqlite:///etc/ipsec.d/ipsec.db
+    }
+  }
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+
+  keep_alive = 5
+}
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
new file mode 100644
index 0000000..50eccad
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.conf
@@ -0,0 +1,3 @@
+# /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
new file mode 100644
index 0000000..4e99759
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.d/data.sql
@@ -0,0 +1,195 @@
+/* Identities */
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
+  9, X'3045310B300906035504061302434831193017060355040A13104C696E7578207374726F6E675377616E311B3019060355040313127374726F6E675377616E20526F6F74204341'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
+  11, X'5da7dd700651327ee7b66db3b5e5e060ea2e4def'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* keyid of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
+  11, X'ae096b87b44886d3b820978623dabd0eae22ebbc'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* sun.strongswan.org */
+  2, X'73756e2e7374726f6e677377616e2e6f7267'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=sun.strongswan.org' */
+  11, X'56d69e2fdaa8a1cd195c2353e7c5b67096e30bfb'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* %any */
+  0, '%any'
+);
+
+/* Certificates */
+
+INSERT INTO certificates (
+   type, keytype, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
+  1, 1, X'308203b53082029da003020102020100300d06092a864886f70d01010405003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3034303931303131303134355a170d3134303930383131303134355a3045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f7420434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bff25f [...]
+);
+
+INSERT INTO certificates (
+   type, keytype, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=sun.strongswan.org */
+  1, 1, X'3082042030820308a003020102020116300d06092a864886f70d01010b05003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3039303832373039353930345a170d3134303832363039353930345a3045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b30190603550403131273756e2e7374726f6e677377616e2e6f726730820122300d06092a864886f70d01010105000382010f003082010a0282010100df9554 [...]
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 1
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 2
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 3
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  2, 4
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  2, 5
+);
+
+/* Private Keys */
+
+INSERT INTO private_keys (
+   type, data
+) VALUES ( /* key of 'C=CH, O=Linux strongSwan, CN=sun.strongswan.org' */
+  1, X'308204a40201000282010100df95548a67e90e63694fff10dea9e80e5c49f51f8412b49856b695a145661fd8d21eba017aaaad0dd7f75ee1ed836c4a4ebca28c18f61f48de03b1ee135506c26bd958dd602f9bd2ae4d4e16b4f7f0399a29affe9ad88faa34c9ac31a0f8e80ecf5887b0fb29ff85f1f920934b2d9472595fae89edd36b1576e0d7106577e129e4eaf615b119f50594a51413ba176936dff8f58bb1439f437a663d2116f0b2b2821c7d261ab26c0dda9e6f46a9fbc42f4971e30add5fafd30d29668014040b2902387b475ad67b4f08440b784f37dfe34d441806b9f9342aa193dde017aabc5af401085099d57 [...]
+);
+
+INSERT INTO private_key_identity (
+  private_key, identity
+) VALUES (
+  1, 4
+);
+
+INSERT INTO private_key_identity (
+  private_key, identity
+) VALUES (
+  1, 5
+);
+
+/* Configurations */
+
+INSERT INTO ike_configs (
+  local, remote
+) VALUES (
+  'PH_IP_SUN', '0.0.0.0'
+);
+
+INSERT INTO peer_configs (
+  name, ike_cfg, local_id, remote_id, pool
+) VALUES (
+  'nat-t', 1, 4, 6, 'vips'
+);
+
+INSERT INTO child_configs (
+  name, updown
+) VALUES (
+  'nat-t', 'ipsec _updown iptables'
+);
+
+INSERT INTO peer_config_child_config (
+  peer_cfg, child_cfg
+) VALUES (
+  1, 1
+);
+
+INSERT INTO traffic_selectors (
+  type, start_addr, end_addr
+) VALUES ( /* 0.0.0.0/0 */
+  7, X'00000000', X'ffffffff'
+);
+
+INSERT INTO traffic_selectors (
+  type
+) VALUES ( /* dynamic/32 */
+  7
+);
+
+INSERT INTO child_config_traffic_selector (
+  child_cfg, traffic_selector, kind
+) VALUES (
+  1, 1, 0
+);
+
+INSERT INTO child_config_traffic_selector (
+	child_cfg, traffic_selector, kind
+) VALUES (
+  1, 2, 3
+);
+
+/* Pools */
+
+INSERT INTO pools (
+  name, start, end, timeout
+) VALUES (
+  'vips', X'0a030001', X'0a030006', 0
+);
+
+INSERT INTO addresses (
+  pool, address
+) VALUES (
+  1, X'0a030001'
+);
+
+INSERT INTO addresses (
+  pool, address
+) VALUES (
+  1, X'0a030002'
+);
+
+INSERT INTO addresses (
+  pool, address
+) VALUES (
+  1, X'0a030003'
+);
+
+INSERT INTO addresses (
+  pool, address
+) VALUES (
+  1, X'0a030004'
+);
+
+INSERT INTO addresses (
+  pool, address
+) VALUES (
+  1, X'0a030005'
+);
+
+INSERT INTO addresses (
+  pool, address
+) VALUES (
+  1, X'0a030006'
+);
diff --git a/testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.secrets b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.secrets
rename to testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/ipsec.secrets
diff --git a/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/iptables.rules
new file mode 100644
index 0000000..ae8f9a6
--- /dev/null
+++ b/testing/tests/sql/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/sql/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
new file mode 100644
index 0000000..16e9349
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  plugins {
+    sql {
+      database = sqlite:///etc/ipsec.d/ipsec.db
+    }
+    attr-sql {
+      database = sqlite:///etc/ipsec.d/ipsec.db
+    }
+  }
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown sqlite sql attr-sql
+}
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
new file mode 100644
index 0000000..50eccad
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.conf
@@ -0,0 +1,3 @@
+# /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.d/data.sql b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.d/data.sql
new file mode 100644
index 0000000..e00d00e
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.d/data.sql
@@ -0,0 +1,199 @@
+/* Identities */
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
+  9, X'3045310B300906035504061302434831193017060355040A13104C696E7578207374726F6E675377616E311B3019060355040313127374726F6E675377616E20526F6F74204341'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
+  11, X'5da7dd700651327ee7b66db3b5e5e060ea2e4def'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* keyid of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
+  11, X'ae096b87b44886d3b820978623dabd0eae22ebbc'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* venus.strongswan.org */
+  2, X'76656e75732e7374726f6e677377616e2e6f7267'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* sun.strongswan.org */
+  2, X'73756e2e7374726f6e677377616e2e6f7267'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=venus.strongswan.org' */
+  11, X'8f5c0a6cb147fc1b51708046e0636c7a54012d67'
+ );
+
+INSERT INTO identities (
+  type, data
+) VALUES ( /* %any */
+  0, '%any'
+);
+
+/* Certificates */
+
+INSERT INTO certificates (
+   type, keytype, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
+  1, 1, X'308203b53082029da003020102020100300d06092a864886f70d01010405003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3034303931303131303134355a170d3134303930383131303134355a3045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f7420434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bff25f [...]
+);
+
+INSERT INTO certificates (
+   type, keytype, data
+) VALUES ( /* C=CH, O=Linux strongSwan, CN=venus.strongswan.org */
+  1, 1, X'3082040f308202f7a003020102020118300d06092a864886f70d01010b05003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3039303832373130303532325a170d3134303832363130303532325a3047310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311d301b0603550403131476656e75732e7374726f6e677377616e2e6f726730820122300d06092a864886f70d01010105000382010f003082010a0282010100b3 [...]
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 1
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 2
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  1, 3
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  2, 4
+);
+
+INSERT INTO certificate_identity (
+  certificate, identity
+) VALUES (
+  2, 6
+);
+
+/* Private Keys */
+
+INSERT INTO private_keys (
+   type, data
+) VALUES ( /* key of 'C=CH, O=Linux strongSwan, CN=venus.strongswan.org' */
+  1, X'308204a20201000282010100b3452cb2d9328eebcd929c7fbe66652a90484c9c8699f4df163974d6e538754570cc4df28659463cb3778a32d2b5e1cfde8a546c335de5d1b8795b1af43522a8826593f83eb67292e487506c0eb251fd67207af7f6d56e90eb57ebab0c787054f8ce3a283eebe1146b1920584f516cc88bf8ec3dae936e27059ed27f6f8ba154197cc21577274819f1f1990271ca6cd2f349a1e7b10ddb2ef4a07f473309ff6db19bf16af2b0dd3d5956cd6d3daf75e617dce2578b4c6c993fd89debf5543f41da66c0fd709fe1ce39c452f51f1290ffe45396663acfa9b8ac116e1460ac70b3db6b9836f7499 [...]
+);
+
+INSERT INTO private_key_identity (
+  private_key, identity
+) VALUES (
+  1, 4
+);
+
+INSERT INTO private_key_identity (
+  private_key, identity
+) VALUES (
+  1, 6
+);
+
+/* Configurations */
+
+INSERT INTO ike_configs (
+  local, remote
+) VALUES (
+  'PH_IP_VENUS', 'PH_IP_SUN'
+);
+
+INSERT INTO ike_configs (
+  local, remote
+) VALUES (
+  '%any', '%any'
+);
+
+INSERT INTO peer_configs (
+  name, ike_cfg, local_id, remote_id, virtual
+) VALUES (
+  'nat-t', 1, 4, 5, '0.0.0.0'
+);
+
+INSERT INTO peer_configs (
+  name, ike_cfg, local_id, remote_id, auth_method
+) VALUES (
+  'shunts', 2, 7, 7, 0
+);
+
+INSERT INTO child_configs (
+  name
+) VALUES (
+  'nat-t'
+);
+
+INSERT INTO child_configs (
+  name, mode, start_action
+) VALUES (
+  'local-net', 4, 1
+);
+
+INSERT INTO peer_config_child_config (
+  peer_cfg, child_cfg
+) VALUES (
+  1, 1
+);
+
+INSERT INTO peer_config_child_config (
+  peer_cfg, child_cfg
+) VALUES (
+  2, 2
+);
+
+INSERT INTO traffic_selectors (
+  type, start_addr, end_addr
+) VALUES ( /* 10.1.0.0/16 */
+  7, X'0a010000', X'0a01ffff'
+);
+
+INSERT INTO traffic_selectors (
+  type, start_addr, end_addr
+) VALUES ( /* 0.0.0.0/0 */
+  7, X'00000000', X'ffffffff'
+);
+
+INSERT INTO traffic_selectors (
+  type
+) VALUES ( /* dynamic/32 */
+  7
+);
+
+INSERT INTO child_config_traffic_selector (
+  child_cfg, traffic_selector, kind
+) VALUES (
+  1, 2, 1
+);
+
+INSERT INTO child_config_traffic_selector (
+	child_cfg, traffic_selector, kind
+) VALUES (
+  1, 3, 2
+);
+
+INSERT INTO child_config_traffic_selector (
+	child_cfg, traffic_selector, kind
+) VALUES (
+  2, 1, 0
+);
+
+INSERT INTO child_config_traffic_selector (
+	child_cfg, traffic_selector, kind
+) VALUES (
+  2, 1, 1
+);
diff --git a/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.secrets b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.secrets
rename to testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/ipsec.secrets
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
new file mode 100644
index 0000000..2f01cdc
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/hosts/venus/etc/strongswan.conf
@@ -0,0 +1,12 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  plugins {
+    sql {
+      database = sqlite:///etc/ipsec.d/ipsec.db
+    }
+  }
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown sqlite sql
+
+  keep_alive = 5
+}
diff --git a/testing/tests/sql/shunt-policies-nat-rw/posttest.dat b/testing/tests/sql/shunt-policies-nat-rw/posttest.dat
new file mode 100644
index 0000000..f410dd7
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/posttest.dat
@@ -0,0 +1,8 @@
+sun::ipsec stop
+alice::ipsec stop
+venus::ipsec stop
+sun::iptables-restore < /etc/iptables.flush
+alice::rm /etc/ipsec.d/ipsec.*
+venus::rm /etc/ipsec.d/ipsec.*
+sun::rm /etc/ipsec.d/ipsec.*
+moon::iptables -t nat -F
\ No newline at end of file
diff --git a/testing/tests/sql/shunt-policies-nat-rw/pretest.dat b/testing/tests/sql/shunt-policies-nat-rw/pretest.dat
new file mode 100644
index 0000000..0314e7a
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/pretest.dat
@@ -0,0 +1,20 @@
+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/ipsec.d/ipsec.sql
+venus::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/ipsec.d/ipsec.sql
+sun::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/ipsec.d/ipsec.sql
+alice::cat /etc/ipsec.d/ipsec.sql | sqlite3 /etc/ipsec.d/ipsec.db
+venus::cat /etc/ipsec.d/ipsec.sql | sqlite3 /etc/ipsec.d/ipsec.db
+sun::cat /etc/ipsec.d/ipsec.sql | sqlite3 /etc/ipsec.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
+alice::expect-connection nat-t
+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
diff --git a/testing/tests/sql/shunt-policies-nat-rw/test.conf b/testing/tests/sql/shunt-policies-nat-rw/test.conf
new file mode 100644
index 0000000..bd82f03
--- /dev/null
+++ b/testing/tests/sql/shunt-policies-nat-rw/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 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"
diff --git a/testing/tests/sql/shunt-policies/description.txt b/testing/tests/sql/shunt-policies/description.txt
deleted file mode 100644
index 269e795..0000000
--- a/testing/tests/sql/shunt-policies/description.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-All traffic from the clients <b>alice</b> and <b>venus</b> is tunneled
-by default gateway <b>moon</b> to VPN gateway <b>sun</b>. In order to
-prevent local traffic within the <b>10.1.0.0/16</b> subnet to enter the
-tunnel, a <b>local-net</b> shunt policy with <b>type=pass</b> is set up.
-In order for the shunt to work, automatic route insertion must be disabled
-by adding <b>install_routes = no</b> to the charon section of <b>strongswan.conf</b>.
-<p/>
-In order to demonstrate the use of <b>type=drop</b> shunt policies, the
-<b>venus-icmp</b> connection prevents ICMP traffic to and from <b>venus</b>
-to use the IPsec tunnel by dropping such packets. Thanks to the <b>local-net</b>
-pass shunt, <b>venus</b> and <b>moon</b> can still ping each other, though.
diff --git a/testing/tests/sql/shunt-policies/evaltest.dat b/testing/tests/sql/shunt-policies/evaltest.dat
deleted file mode 100644
index 51dd961..0000000
--- a/testing/tests/sql/shunt-policies/evaltest.dat
+++ /dev/null
@@ -1,20 +0,0 @@
-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:: ipsec status 2> /dev/null::local-net.*PASS::YES
-moon:: ipsec status 2> /dev/null::venus-icmp.*DROP::YES
-alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
-alice::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-venus::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::NO
-venus::ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-moon:: ping -c 1 -I PH_IP_MOON1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES
-moon:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-moon:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_MOON1::64 bytes from PH_IP_MOON1: icmp_req=1::YES
-bob::  ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
-sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
-sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
-venus::ssh PH_IP_BOB hostname::bob::YES
-bob::ssh PH_IP_VENUS hostname::venus::YES
diff --git a/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.conf b/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.conf
deleted file mode 100644
index a7fa092..0000000
--- a/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.d/data.sql b/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.d/data.sql
deleted file mode 100644
index 4ece72c..0000000
--- a/testing/tests/sql/shunt-policies/hosts/moon/etc/ipsec.d/data.sql
+++ /dev/null
@@ -1,227 +0,0 @@
-/* Identities */
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
-  9, X'3045310B300906035504061302434831193017060355040A13104C696E7578207374726F6E675377616E311B3019060355040313127374726F6E675377616E20526F6F74204341'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
-  11, X'5da7dd700651327ee7b66db3b5e5e060ea2e4def'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* keyid of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
-  11, X'ae096b87b44886d3b820978623dabd0eae22ebbc'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* moon.strongswan.org */
-  2, X'6d6f6f6e2e7374726f6e677377616e2e6f7267'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* sun.strongswan.org */
-  2, X'73756e2e7374726f6e677377616e2e6f7267'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=moon.strongswan.org' */
-  11, X'6a9c74d1f8897989f65a94e989f1fac3649d292e'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* %any */
-  0, '%any'
-);
-
-/* Certificates */
-
-INSERT INTO certificates (
-   type, keytype, data
-) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
-  1, 1, X'308203b53082029da003020102020100300d06092a864886f70d01010405003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3034303931303131303134355a170d3134303930383131303134355a3045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f7420434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bff25f [...]
-);
-
-INSERT INTO certificates (
-   type, keytype, data
-) VALUES ( /* C=CH, O=Linux strongSwan, CN=moon.strongswan.org */
-  1, 1, X'308204223082030aa003020102020117300d06092a864886f70d01010b05003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3039303832373130303333325a170d3134303832363130303333325a3046310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311c301a060355040313136d6f6f6e2e7374726f6e677377616e2e6f726730820122300d06092a864886f70d01010105000382010f003082010a0282010100ca2f [...]
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  1, 1
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  1, 2
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  1, 3
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  2, 4 
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  2, 6 
-);
-
-/* Private Keys */
-
-INSERT INTO private_keys (
-   type, data
-) VALUES ( /* key of 'C=CH, O=Linux strongSwan, CN=moon.strongswan.org' */
-  1, X'308204a30201000282010100ca2f633dd4bbba0586215b15a0312f73f533124f0b339b9ae13bb648b02b4c468e0f01e630fbef92197b7708f5dbffea7e496286966d75acf13bd5e4377a1821d82de102eadf9963b489041a0b0f9f76b79e2150aa39020e3fa52a677dbb879c986291e4f1542fe2f0494e9c5c954d4faa75a17aa7b56652f1b16efbdcb46697f7d0b7f520bc990205365938d2cd31f2beed30e761a56c02d9dc82f0cdefc9d43447b6a98f7628aed2ac127a4a9504838f66e7517e5e0b0672c8165474bce689f73a6fc6e3c72b2c45498ddbbc0b17b04915606fe94f256cc777c42c534560ffbbe5aacdd944c [...]
-);
-
-INSERT INTO private_key_identity (
-  private_key, identity
-) VALUES (
-  1, 4 
-);
-
-INSERT INTO private_key_identity (
-  private_key, identity
-) VALUES (
-  1, 6 
-);
-
-/* Configurations */
-
-INSERT INTO ike_configs (
-  local, remote
-) VALUES (
-  'PH_IP_MOON', 'PH_IP_SUN'
-);
-
-INSERT INTO ike_configs (
-  local, remote
-) VALUES (
-  '%any', '%any'
-);
-
-INSERT INTO peer_configs (
-  name, ike_cfg, local_id, remote_id, mobike, dpd_delay
-) VALUES (
-  'net-net', 1, 4, 5, 0, 0
-);
-
-INSERT INTO peer_configs (
-  name, ike_cfg, local_id, remote_id, auth_method, mobike, dpd_delay
-) VALUES (
-  'shunts', 2, 7, 7, 0, 0, 0
-);
-INSERT INTO child_configs (
-  name, updown, hostaccess
-) VALUES (
-  'net-net', 'ipsec _updown iptables', 1
-);
-
-INSERT INTO child_configs (
-  name, mode, start_action
-) VALUES (
-  'local-net', 4, 1
-);
-
-INSERT INTO child_configs (
-  name, mode, start_action
-) VALUES (
-  'venus-icmp', 5, 1
-);
-
-INSERT INTO peer_config_child_config (
-  peer_cfg, child_cfg
-) VALUES (
-  1, 1
-);
-
-INSERT INTO peer_config_child_config (
-  peer_cfg, child_cfg
-) VALUES (
-  2, 2
-);
-
-INSERT INTO peer_config_child_config (
-  peer_cfg, child_cfg
-) VALUES (
-  2, 3
-);
-INSERT INTO traffic_selectors (
-  type, start_addr, end_addr
-) VALUES (
-  7, X'0a010000', X'0a01ffff'
-);
-
-INSERT INTO traffic_selectors (
-  type, start_addr, end_addr
-) VALUES (
-  7, X'00000000', X'ffffffff'
-);
-
-INSERT INTO traffic_selectors (
-  type, start_addr, end_addr, protocol
-) VALUES (
-  7, X'0a010014', X'0a010014', 1
-);
-
-INSERT INTO traffic_selectors (
-  type, start_addr, end_addr, protocol
-) VALUES (
-  7, X'00000000', X'ffffffff', 1
-);
-
-INSERT INTO child_config_traffic_selector (
-  child_cfg, traffic_selector, kind
-) VALUES (
-  1, 1, 0
-);
-
-INSERT INTO child_config_traffic_selector (
-	child_cfg, traffic_selector, kind
-) VALUES (
-  1, 2, 1
-);
-
-INSERT INTO child_config_traffic_selector (
-	child_cfg, traffic_selector, kind
-) VALUES (
-  2, 1, 0
-);
-
-INSERT INTO child_config_traffic_selector (
-	child_cfg, traffic_selector, kind
-) VALUES (
-  2, 1, 1
-);
-
-INSERT INTO child_config_traffic_selector (
-	child_cfg, traffic_selector, kind
-) VALUES (
-  3, 3, 0
-);
-
-INSERT INTO child_config_traffic_selector (
-	child_cfg, traffic_selector, kind
-) VALUES (
-  3, 4, 1
-);
diff --git a/testing/tests/sql/shunt-policies/hosts/moon/etc/iptables.rules b/testing/tests/sql/shunt-policies/hosts/moon/etc/iptables.rules
deleted file mode 100644
index af0f252..0000000
--- a/testing/tests/sql/shunt-policies/hosts/moon/etc/iptables.rules
+++ /dev/null
@@ -1,32 +0,0 @@
-*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 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
-
-# allow icmp in local net
--A INPUT  -i eth1 -p icmp -j ACCEPT
--A OUTPUT -o eth1 -p icmp -j ACCEPT
-
-COMMIT
diff --git a/testing/tests/sql/shunt-policies/hosts/moon/etc/strongswan.conf b/testing/tests/sql/shunt-policies/hosts/moon/etc/strongswan.conf
deleted file mode 100644
index b3a7bc0..0000000
--- a/testing/tests/sql/shunt-policies/hosts/moon/etc/strongswan.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  plugins {
-    sql {
-      database = sqlite:///etc/ipsec.d/ipsec.db 
-    }
-  }
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown sqlite sql
-  install_routes = no
-}
diff --git a/testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.conf b/testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.conf
deleted file mode 100644
index a7fa092..0000000
--- a/testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-
-# configuration is read from SQLite database
diff --git a/testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.d/data.sql b/testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.d/data.sql
deleted file mode 100644
index 3a0fe67..0000000
--- a/testing/tests/sql/shunt-policies/hosts/sun/etc/ipsec.d/data.sql
+++ /dev/null
@@ -1,152 +0,0 @@
-/* Identities */
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
-  9, X'3045310B300906035504061302434831193017060355040A13104C696E7578207374726F6E675377616E311B3019060355040313127374726F6E675377616E20526F6F74204341'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
-  11, X'5da7dd700651327ee7b66db3b5e5e060ea2e4def'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* keyid of 'C=CH, O=Linux strongSwan, CN=strongSwan Root CA' */
-  11, X'ae096b87b44886d3b820978623dabd0eae22ebbc'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* moon.strongswan.org */
-  2, X'6d6f6f6e2e7374726f6e677377616e2e6f7267'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* sun.strongswan.org */
-  2, X'73756e2e7374726f6e677377616e2e6f7267'
- );
-
-INSERT INTO identities (
-  type, data
-) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, CN=sun.strongswan.org' */
-  11, X'56d69e2fdaa8a1cd195c2353e7c5b67096e30bfb'
- );
-
-/* Certificates */
-
-INSERT INTO certificates (
-   type, keytype, data
-) VALUES ( /* C=CH, O=Linux strongSwan, CN=strongSwan Root CA */
-  1, 1, X'308203b53082029da003020102020100300d06092a864886f70d01010405003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3034303931303131303134355a170d3134303930383131303134355a3045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f7420434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bff25f [...]
-);
-
-INSERT INTO certificates (
-   type, keytype, data
-) VALUES ( /* C=CH, O=Linux strongSwan, CN=sun.strongswan.org */
-  1, 1, X'3082042030820308a003020102020116300d06092a864886f70d01010b05003045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b3019060355040313127374726f6e675377616e20526f6f74204341301e170d3039303832373039353930345a170d3134303832363039353930345a3045310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e311b30190603550403131273756e2e7374726f6e677377616e2e6f726730820122300d06092a864886f70d01010105000382010f003082010a0282010100df9554 [...]
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  1, 1
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  1, 2
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  1, 3
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  2, 5 
-);
-
-INSERT INTO certificate_identity (
-  certificate, identity
-) VALUES (
-  2, 6 
-);
-
-/* Private Keys */
-
-INSERT INTO private_keys (
-   type, data
-) VALUES ( /* key of 'C=CH, O=Linux strongSwan, CN=sun.strongswan.org' */
-  1, X'308204a40201000282010100df95548a67e90e63694fff10dea9e80e5c49f51f8412b49856b695a145661fd8d21eba017aaaad0dd7f75ee1ed836c4a4ebca28c18f61f48de03b1ee135506c26bd958dd602f9bd2ae4d4e16b4f7f0399a29affe9ad88faa34c9ac31a0f8e80ecf5887b0fb29ff85f1f920934b2d9472595fae89edd36b1576e0d7106577e129e4eaf615b119f50594a51413ba176936dff8f58bb1439f437a663d2116f0b2b2821c7d261ab26c0dda9e6f46a9fbc42f4971e30add5fafd30d29668014040b2902387b475ad67b4f08440b784f37dfe34d441806b9f9342aa193dde017aabc5af401085099d57 [...]
-);
-
-INSERT INTO private_key_identity (
-  private_key, identity
-) VALUES (
-  1, 5 
-);
-
-INSERT INTO private_key_identity (
-  private_key, identity
-) VALUES (
-  1, 6 
-);
-
-/* Configurations */
-
-INSERT INTO ike_configs (
-  local, remote
-) VALUES (
-  'PH_IP_SUN', 'PH_IP_MOON'
-);
-
-INSERT INTO peer_configs (
-  name, ike_cfg, local_id, remote_id, mobike, dpd_delay
-) VALUES (
-  'net-net', 1, 5, 4, 0, 0
-);
-
-INSERT INTO child_configs (
-  name, updown
-) VALUES (
-  'net-net', 'ipsec _updown iptables'
-);
-
-INSERT INTO peer_config_child_config (
-  peer_cfg, child_cfg
-) VALUES (
-  1, 1
-);
-
-INSERT INTO traffic_selectors (
-  type, start_addr, end_addr
-) VALUES (
-  7, X'0a010000', X'0a01ffff'
-);
-
-INSERT INTO traffic_selectors (
-  type, start_addr, end_addr
-) VALUES (
-  7, X'00000000', X'ffffffff'
-);
-
-INSERT INTO child_config_traffic_selector (
-  child_cfg, traffic_selector, kind
-) VALUES (
-  1, 2, 0
-);
-
-INSERT INTO child_config_traffic_selector (
-	child_cfg, traffic_selector, kind
-) VALUES (
-  1, 1, 1
-);
-
diff --git a/testing/tests/sql/shunt-policies/hosts/sun/etc/strongswan.conf b/testing/tests/sql/shunt-policies/hosts/sun/etc/strongswan.conf
deleted file mode 100644
index 930b725..0000000
--- a/testing/tests/sql/shunt-policies/hosts/sun/etc/strongswan.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  plugins {
-    sql {
-      database = sqlite:///etc/ipsec.d/ipsec.db 
-    }
-  }
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown sqlite sql
-}
diff --git a/testing/tests/sql/shunt-policies/posttest.dat b/testing/tests/sql/shunt-policies/posttest.dat
deleted file mode 100644
index 329a572..0000000
--- a/testing/tests/sql/shunt-policies/posttest.dat
+++ /dev/null
@@ -1,6 +0,0 @@
-moon::ipsec stop
-sun::ipsec stop
-moon::iptables-restore < /etc/iptables.flush
-sun::iptables-restore < /etc/iptables.flush
-moon::rm /etc/ipsec.d/ipsec.*
-sun::rm /etc/ipsec.d/ipsec.*
diff --git a/testing/tests/sql/shunt-policies/pretest.dat b/testing/tests/sql/shunt-policies/pretest.dat
deleted file mode 100644
index b62da61..0000000
--- a/testing/tests/sql/shunt-policies/pretest.dat
+++ /dev/null
@@ -1,12 +0,0 @@
-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/ipsec.d/ipsec.sql
-sun::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql /etc/ipsec.d/data.sql > /etc/ipsec.d/ipsec.sql
-moon::cat /etc/ipsec.d/ipsec.sql | sqlite3 /etc/ipsec.d/ipsec.db
-sun::cat /etc/ipsec.d/ipsec.sql | sqlite3 /etc/ipsec.d/ipsec.db
-moon::iptables-restore < /etc/iptables.rules
-sun::iptables-restore < /etc/iptables.rules
-moon::ipsec start
-sun::ipsec start
-moon::sleep 1
-moon::ipsec up net-net
diff --git a/testing/tests/swanctl/ip-pool-db/description.txt b/testing/tests/swanctl/ip-pool-db/description.txt
new file mode 100755
index 0000000..9774e57
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/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>.
+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. The gateway <b>moon</b> assigns virtual IP
+addresses from a pool named <b>bigpool</b> that was created in an SQL database by the command
+<b>ipsec pool --name bigpool --start 10.3.0.1 --end 10.3.3.232 --timeout 0</b>.
+<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/ip-pool-db/evaltest.dat b/testing/tests/swanctl/ip-pool-db/evaltest.dat
new file mode 100755
index 0000000..f76c356
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/evaltest.dat
@@ -0,0 +1,23 @@
+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]
+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
+moon:: ipsec pool --leases --filter pool=big_pool,addr=10.3.0.1,id=carol at strongswan.org 2> /dev/null::online::YES
+moon:: ipsec pool --leases --filter pool=big_pool,addr=10.3.0.2,id=dave at strongswan.org 2> /dev/null::online::YES
+carol::cat /var/log/daemon.log::installing new virtual IP 10.3.0.1::YES
+carol::cat /var/log/daemon.log::installing DNS server PH_IP_WINNETOU::YES
+carol::cat /var/log/daemon.log::installing DNS server PH_IP_VENUS::YES
+carol::cat /var/log/daemon.log::handling INTERNAL_IP4_NBNS attribute failed::YES
+dave:: cat /var/log/daemon.log::installing new virtual IP 10.3.0.2::YES
+dave:: cat /var/log/daemon.log::installing DNS server PH_IP_WINNETOU::YES
+dave:: cat /var/log/daemon.log::installing DNS server PH_IP_VENUS::YES
+dave:: cat /var/log/daemon.log::handling INTERNAL_IP4_NBNS attribute failed::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/ip-pool-db/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/ip-pool-db/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..8f87a52
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,11 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  dh_exponent_ansi_x9_42 = no
+
+  load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default resolve updown vici 
+}
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
new file mode 100755
index 0000000..0bb3414
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,33 @@
+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 
+
+            start_action = none
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            rekey_time = 10m 
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..8f87a52
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,11 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  dh_exponent_ansi_x9_42 = no
+
+  load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default resolve updown vici 
+}
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
new file mode 100755
index 0000000..24d2f86
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,33 @@
+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 
+
+            start_action = none
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            rekey_time = 10m 
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..2f63228
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,21 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+swanctl {
+  load = pem pkcs1 x509 revocation constraints pubkey openssl random 
+}
+
+charon {
+  dh_exponent_ansi_x9_42 = no
+
+  load = sha1 sha2 md5 aes des hmac pem pkcs1 x509 revocation constraints pubkey gmp random nonce curl kernel-netlink socket-default updown sqlite attr-sql vici 
+
+  plugins {
+    attr-sql {
+      database = sqlite:///etc/ipsec.d/ipsec.db
+    }
+  }
+}
+
+pool {
+  load = sqlite
+}
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
new file mode 100755
index 0000000..d05dea0
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,31 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+      pools = big_pool
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/ip-pool-db/posttest.dat b/testing/tests/swanctl/ip-pool-db/posttest.dat
new file mode 100755
index 0000000..2644b39
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/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::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
+moon::ipsec pool --del big_pool 2> /dev/null
+moon::ipsec pool --del dns 2> /dev/null
+moon::ipsec pool --del nbns 2> /dev/null
diff --git a/testing/tests/swanctl/ip-pool-db/pretest.dat b/testing/tests/swanctl/ip-pool-db/pretest.dat
new file mode 100755
index 0000000..0607f67
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/pretest.dat
@@ -0,0 +1,21 @@
+moon::cat /usr/local/share/strongswan/templates/database/sql/sqlite.sql > /etc/ipsec.d/ipsec.sql
+moon::cat /etc/ipsec.d/ipsec.sql | sqlite3 /etc/ipsec.d/ipsec.db
+moon::ipsec pool --add big_pool --start 10.3.0.1 --end 10.3.3.232 --timeout 0 2> /dev/null
+moon::ipsec pool --addattr dns  --server PH_IP_WINNETOU 2> /dev/null
+moon::ipsec pool --addattr dns  --server PH_IP_VENUS 2> /dev/null
+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 
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::sleep 1
+moon::swanctl --load-conns 2> /dev/null
+carol::swanctl --load-conns 2> /dev/null
+dave::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+carol::swanctl --load-creds 2> /dev/null
+dave::swanctl --load-creds 2> /dev/null
+carol::swanctl --initiate --child home 2> /dev/null
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/ip-pool-db/test.conf b/testing/tests/swanctl/ip-pool-db/test.conf
new file mode 100755
index 0000000..f292988
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool-db/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 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"
diff --git a/testing/tests/swanctl/ip-pool/description.txt b/testing/tests/swanctl/ip-pool/description.txt
new file mode 100755
index 0000000..23cab8e
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/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>.
+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. The gateway <b>moon</b> assigns virtual
+IP addresses from a simple pool defined by <b>rightsourceip=10.3.0.0/28</b> in a monotonously
+increasing order. 
+<p>
+<b>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/ip-pool/evaltest.dat b/testing/tests/swanctl/ip-pool/evaltest.dat
new file mode 100755
index 0000000..a16ed01
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/evaltest.dat
@@ -0,0 +1,15 @@
+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]
+moon:: swanctl --list-pools --raw 2> /dev/null::rw_pool.*base=10.3.0.0 size=14 online=2 offline=0::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/ip-pool/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/ip-pool/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..0bb3414
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,33 @@
+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 
+
+            start_action = none
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            rekey_time = 10m 
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/ip-pool/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/ip-pool/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..24d2f86
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,33 @@
+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 
+
+            start_action = none
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            rekey_time = 10m 
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/ip-pool/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/ip-pool/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..aa31d0f
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,37 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+      pools = rw_pool
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+pools {
+   rw_pool {
+      addrs = 10.3.0.0/28
+   }
+}
diff --git a/testing/tests/swanctl/ip-pool/posttest.dat b/testing/tests/swanctl/ip-pool/posttest.dat
new file mode 100755
index 0000000..d7107cc
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/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/ip-pool/pretest.dat b/testing/tests/swanctl/ip-pool/pretest.dat
new file mode 100755
index 0000000..d1afdf0
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/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::service charon start 2> /dev/null 
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::swanctl --load-conns 2> /dev/null
+carol::swanctl --load-conns 2> /dev/null
+dave::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+carol::swanctl --load-creds 2> /dev/null
+dave::swanctl --load-creds 2> /dev/null
+moon::swanctl --load-pools 2> /dev/null
+carol::swanctl --initiate --child home 2> /dev/null
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/ip-pool/test.conf b/testing/tests/swanctl/ip-pool/test.conf
new file mode 100755
index 0000000..f292988
--- /dev/null
+++ b/testing/tests/swanctl/ip-pool/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 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"
diff --git a/testing/tests/swanctl/net2net-cert/description.txt b/testing/tests/swanctl/net2net-cert/description.txt
new file mode 100755
index 0000000..345769a
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/description.txt
@@ -0,0 +1,6 @@
+A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
+The authentication is based on <b>X.509 certificates</b>. Upon the successful
+establishment of the IPsec tunnel, the updown script 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-cert/evaltest.dat b/testing/tests/swanctl/net2net-cert/evaltest.dat
new file mode 100755
index 0000000..cdbecd5
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/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-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
+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/strongswan.conf b/testing/tests/swanctl/net2net-cert/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..2f0fd9d
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.2 
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = sun.strongswan.org 
+      }
+      children {
+         net-net {
+            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
+         }
+      }
+
+      version = 2
+      mobike = no
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/net2net-cert/hosts/sun/etc/strongswan.conf b/testing/tests/swanctl/net2net-cert/hosts/sun/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..e4c8556
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.2
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = sunCert.pem
+         id = sun.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         net-net {
+            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
+         }
+      }
+
+      version = 2
+      mobike = no
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/net2net-cert/posttest.dat b/testing/tests/swanctl/net2net-cert/posttest.dat
new file mode 100755
index 0000000..30d10b5
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/posttest.dat
@@ -0,0 +1,5 @@
+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
diff --git a/testing/tests/swanctl/net2net-cert/pretest.dat b/testing/tests/swanctl/net2net-cert/pretest.dat
new file mode 100755
index 0000000..2c4ba6c
--- /dev/null
+++ b/testing/tests/swanctl/net2net-cert/pretest.dat
@@ -0,0 +1,9 @@
+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::swanctl --load-conns 2> /dev/null
+sun::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+sun::swanctl --load-creds 2> /dev/null
+moon::swanctl --initiate --child net-net 2> /dev/null
diff --git a/testing/tests/sql/shunt-policies/test.conf b/testing/tests/swanctl/net2net-cert/test.conf
old mode 100644
new mode 100755
similarity index 100%
copy from testing/tests/sql/shunt-policies/test.conf
copy to testing/tests/swanctl/net2net-cert/test.conf
diff --git a/testing/tests/swanctl/net2net-route/description.txt b/testing/tests/swanctl/net2net-route/description.txt
new file mode 100755
index 0000000..20640ef
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/description.txt
@@ -0,0 +1,9 @@
+A tunnel that will connect the subnets behind the gateways <b>moon</b>
+and <b>sun</b>, respectively, is preconfigured by installing a %trap eroute
+on gateway <b>moon</b> by means of the setting <b>auto=route</b> in ipsec.conf.
+A subsequent ping issued by client <b>alice</b> behind gateway <b>moon</b> to
+<b>bob</b> located behind gateway <b>sun</b> triggers the %trap eroute and
+leads to the automatic establishment of the subnet-to-subnet tunnel.
+<p>
+The updown script automatically inserts iptables-based firewall rules
+that let pass the tunneled traffic.
diff --git a/testing/tests/swanctl/net2net-route/evaltest.dat b/testing/tests/swanctl/net2net-route/evaltest.dat
new file mode 100755
index 0000000..04df90b
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/evaltest.dat
@@ -0,0 +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
+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/strongswan.conf b/testing/tests/swanctl/net2net-route/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..1dfcfd1
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.2 
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = sun.strongswan.org 
+      }
+      children {
+         net-net {
+            local_ts  = 10.1.0.0/16 
+            remote_ts = 10.2.0.0/16 
+
+            start_action = trap 
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            rekey_time = 10m 
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+
+      version = 2
+      mobike = no
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/net2net-route/hosts/sun/etc/strongswan.conf b/testing/tests/swanctl/net2net-route/hosts/sun/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..e4c8556
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.2
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = sunCert.pem
+         id = sun.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         net-net {
+            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
+         }
+      }
+
+      version = 2
+      mobike = no
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/net2net-route/posttest.dat b/testing/tests/swanctl/net2net-route/posttest.dat
new file mode 100755
index 0000000..30d10b5
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/posttest.dat
@@ -0,0 +1,5 @@
+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
diff --git a/testing/tests/swanctl/net2net-route/pretest.dat b/testing/tests/swanctl/net2net-route/pretest.dat
new file mode 100755
index 0000000..61e33fa
--- /dev/null
+++ b/testing/tests/swanctl/net2net-route/pretest.dat
@@ -0,0 +1,9 @@
+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 
+sun::swanctl --load-creds 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+sun::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-conns 2> /dev/null
+alice::ping -c 3 10.2.0.10 
diff --git a/testing/tests/sql/shunt-policies/test.conf b/testing/tests/swanctl/net2net-route/test.conf
old mode 100644
new mode 100755
similarity index 100%
copy from testing/tests/sql/shunt-policies/test.conf
copy to testing/tests/swanctl/net2net-route/test.conf
diff --git a/testing/tests/swanctl/net2net-start/description.txt b/testing/tests/swanctl/net2net-start/description.txt
new file mode 100755
index 0000000..9c67ed6
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/description.txt
@@ -0,0 +1,6 @@
+A tunnel connecting the subnets behind the gateways <b>moon</b> and <b>sun</b>,
+respectively, is automatically established by means of the setting
+<b>auto=start</b> in ipsec.conf. The connection is tested by client <b>alice</b>
+behind gateway <b>moon</b> pinging the client <b>bob</b> located behind
+gateway <b>sun</b>. The updown script automatically inserts iptables-based
+firewall rules that let pass the tunneled traffic.
diff --git a/testing/tests/swanctl/net2net-start/evaltest.dat b/testing/tests/swanctl/net2net-start/evaltest.dat
new file mode 100755
index 0000000..cdbecd5
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/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-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
+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/strongswan.conf b/testing/tests/swanctl/net2net-start/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..6770f6a
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.1
+      remote_addrs = 192.168.0.2 
+
+      local {
+         auth = pubkey
+         certs = moonCert.pem
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = sun.strongswan.org 
+      }
+      children {
+         net-net {
+            local_ts  = 10.1.0.0/16 
+            remote_ts = 10.2.0.0/16 
+
+            start_action = start 
+            updown = /usr/local/libexec/ipsec/_updown iptables
+            rekey_time = 10m 
+            esp_proposals = aes128gcm128-modp2048
+         }
+      }
+
+      version = 2
+      mobike = no
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/net2net-start/hosts/sun/etc/strongswan.conf b/testing/tests/swanctl/net2net-start/hosts/sun/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/hosts/sun/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..e4c8556
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/hosts/sun/etc/swanctl/swanctl.conf
@@ -0,0 +1,34 @@
+connections {
+
+   gw-gw {
+      local_addrs  = 192.168.0.2
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = pubkey
+         certs = sunCert.pem
+         id = sun.strongswan.org
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         net-net {
+            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
+         }
+      }
+
+      version = 2
+      mobike = no
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/net2net-start/posttest.dat b/testing/tests/swanctl/net2net-start/posttest.dat
new file mode 100755
index 0000000..30d10b5
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/posttest.dat
@@ -0,0 +1,5 @@
+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
diff --git a/testing/tests/swanctl/net2net-start/pretest.dat b/testing/tests/swanctl/net2net-start/pretest.dat
new file mode 100755
index 0000000..0560092
--- /dev/null
+++ b/testing/tests/swanctl/net2net-start/pretest.dat
@@ -0,0 +1,9 @@
+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 
+sun::swanctl --load-creds 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+sun::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-conns 2> /dev/null
+moon::sleep 1 
diff --git a/testing/tests/sql/shunt-policies/test.conf b/testing/tests/swanctl/net2net-start/test.conf
old mode 100644
new mode 100755
similarity index 100%
rename from testing/tests/sql/shunt-policies/test.conf
rename to testing/tests/swanctl/net2net-start/test.conf
diff --git a/testing/tests/swanctl/rw-cert/description.txt b/testing/tests/swanctl/rw-cert/description.txt
new file mode 100755
index 0000000..6af7a39
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/description.txt
@@ -0,0 +1,6 @@
+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, 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-cert/evaltest.dat b/testing/tests/swanctl/rw-cert/evaltest.dat
new file mode 100755
index 0000000..bb5e08b
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/evaltest.dat
@@ -0,0 +1,10 @@
+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]
+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
+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-cert/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-cert/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..0ba2433
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/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
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/rw-cert/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-cert/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..a3420a4
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/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
+      }
+      remote {
+         auth = pubkey
+         id = moon.strongswan.org 
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/rw-cert/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-cert/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..75f1847
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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 
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..861d65a
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/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
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
diff --git a/testing/tests/swanctl/rw-cert/posttest.dat b/testing/tests/swanctl/rw-cert/posttest.dat
new file mode 100755
index 0000000..d7107cc
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/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-cert/pretest.dat b/testing/tests/swanctl/rw-cert/pretest.dat
new file mode 100755
index 0000000..3fdf01d
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/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::service charon start 2> /dev/null 
+carol::service charon start 2> /dev/null
+dave::service charon start 2> /dev/null
+moon::swanctl --load-conns 2> /dev/null
+carol::swanctl --load-conns 2> /dev/null
+dave::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+carol::swanctl --load-creds 2> /dev/null
+dave::swanctl --load-creds 2> /dev/null
+carol::swanctl --initiate --child home 2> /dev/null
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-cert/test.conf b/testing/tests/swanctl/rw-cert/test.conf
new file mode 100755
index 0000000..f292988
--- /dev/null
+++ b/testing/tests/swanctl/rw-cert/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 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"
diff --git a/testing/tests/swanctl/rw-psk-fqdn/description.txt b/testing/tests/swanctl/rw-psk-fqdn/description.txt
new file mode 100755
index 0000000..47f6968
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/description.txt
@@ -0,0 +1,6 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
+to gateway <b>moon</b>. The authentication is based on distinct <b>pre-shared keys</b>
+and <b>Fully Qualified Domain Names</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. 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-psk-fqdn/evaltest.dat b/testing/tests/swanctl/rw-psk-fqdn/evaltest.dat
new file mode 100755
index 0000000..bb5e08b
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/evaltest.dat
@@ -0,0 +1,10 @@
+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]
+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
+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-fqdn/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-fqdn/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..772f18a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..c113620
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,41 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = psk
+         id = carol at strongswan.org
+      }
+      remote {
+         auth = psk
+         id = moon.strongswan.org 
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+secrets {
+
+   ike-moon {
+      id = moon.strongswan.org
+      # hex value equal to base64 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
+      secret = 0x16964066a10de938bdb2ab7864fe4459cab1
+   }
+}
+
diff --git a/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..772f18a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..928fd04
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,39 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = psk 
+         id = dave at strongswan.org
+      }
+      remote {
+         auth = psk 
+         id = moon.strongswan.org 
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+secrets {
+
+   ike-moon {
+      id = moon.strongswan.org
+      secret = 0sjVzONCF02ncsgiSlmIXeqhGN
+   }
+}
diff --git a/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..772f18a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..8cae3e8
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,41 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = psk 
+         id = moon.strongswan.org
+      }
+      remote {
+         auth = psk 
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+secrets {
+
+   ike-carol {
+      id = carol at strongswan.org
+      secret = 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
+   }
+   ike-dave {
+      id = dave at strongswan.org
+      secret = 0sjVzONCF02ncsgiSlmIXeqhGN
+   }
+}
diff --git a/testing/tests/swanctl/rw-psk-fqdn/posttest.dat b/testing/tests/swanctl/rw-psk-fqdn/posttest.dat
new file mode 100755
index 0000000..d7107cc
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/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-fqdn/pretest.dat b/testing/tests/swanctl/rw-psk-fqdn/pretest.dat
new file mode 100755
index 0000000..2018f5d
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/pretest.dat
@@ -0,0 +1,17 @@
+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::swanctl --load-conns 2> /dev/null
+carol::swanctl --load-conns 2> /dev/null
+dave::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+carol::swanctl --load-creds 2> /dev/null
+dave::swanctl --load-creds 2> /dev/null
+carol::swanctl --initiate --child home 2> /dev/null
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-psk-fqdn/test.conf b/testing/tests/swanctl/rw-psk-fqdn/test.conf
new file mode 100755
index 0000000..f292988
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-fqdn/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 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"
diff --git a/testing/tests/swanctl/rw-psk-ipv4/description.txt b/testing/tests/swanctl/rw-psk-ipv4/description.txt
new file mode 100755
index 0000000..b4aaa6a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/description.txt
@@ -0,0 +1,6 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
+to gateway <b>moon</b>. The authentication is based on distinct <b>pre-shared keys</b>
+and <b>IPv4</b> addresses. Upon the successful establishment of the IPsec tunnels,
+<b>leftfirewall=yes</b> 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-psk-ipv4/evaltest.dat b/testing/tests/swanctl/rw-psk-ipv4/evaltest.dat
new file mode 100755
index 0000000..142e88e
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/evaltest.dat
@@ -0,0 +1,10 @@
+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]
+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
+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-ipv4/hosts/carol/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-ipv4/hosts/carol/etc/strongswan.conf
new file mode 100755
index 0000000..772f18a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..bd00fc3
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/carol/etc/swanctl/swanctl.conf
@@ -0,0 +1,40 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.100
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = psk
+         id = 192.168.0.100
+      }
+      remote {
+         auth = psk
+         id = 192.168.0.1
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+secrets {
+
+   ike-moon {
+      id = 192.168.0.1 
+      secret = 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
+   }
+}
+
diff --git a/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/strongswan.conf
new file mode 100755
index 0000000..772f18a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..b30790b
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/dave/etc/swanctl/swanctl.conf
@@ -0,0 +1,39 @@
+connections {
+
+   home {
+      local_addrs  = 192.168.0.200
+      remote_addrs = 192.168.0.1 
+
+      local {
+         auth = psk
+         id = 192.168.0.200 
+      }
+      remote {
+         auth = psk
+         id = 192.168.0.1 
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+secrets {
+
+   ike-moon {
+      id = 192.168.0.1 
+      secret = 0sjVzONCF02ncsgiSlmIXeqhGN
+   }
+}
diff --git a/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/strongswan.conf b/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/strongswan.conf
new file mode 100755
index 0000000..772f18a
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,13 @@
+# /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
+}
+
+libstrongswan {
+  dh_exponent_ansi_x9_42 = no
+}
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
new file mode 100755
index 0000000..098b3c0
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/hosts/moon/etc/swanctl/swanctl.conf
@@ -0,0 +1,40 @@
+connections {
+
+   rw {
+      local_addrs  = 192.168.0.1
+
+      local {
+         auth = psk 
+      }
+      remote {
+         auth = psk 
+      }
+      children {
+         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
+         }
+      }
+
+      version = 2
+      reauth_time = 60m
+      rekey_time =  20m
+      proposals = aes128-sha256-modp2048
+   }
+}
+
+secrets {
+
+   ike-carol {
+      id = 192.168.0.100 
+      secret = 0sFpZAZqEN6Ti9sqt4ZP5EWcqx
+   }
+   ike-dave {
+      id = 192.168.0.200
+      secret = 0sjVzONCF02ncsgiSlmIXeqhGN
+   }
+}
diff --git a/testing/tests/swanctl/rw-psk-ipv4/posttest.dat b/testing/tests/swanctl/rw-psk-ipv4/posttest.dat
new file mode 100755
index 0000000..d7107cc
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/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-ipv4/pretest.dat b/testing/tests/swanctl/rw-psk-ipv4/pretest.dat
new file mode 100755
index 0000000..2018f5d
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/pretest.dat
@@ -0,0 +1,17 @@
+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::swanctl --load-conns 2> /dev/null
+carol::swanctl --load-conns 2> /dev/null
+dave::swanctl --load-conns 2> /dev/null
+moon::swanctl --load-creds 2> /dev/null
+carol::swanctl --load-creds 2> /dev/null
+dave::swanctl --load-creds 2> /dev/null
+carol::swanctl --initiate --child home 2> /dev/null
+dave::swanctl --initiate --child home 2> /dev/null
diff --git a/testing/tests/swanctl/rw-psk-ipv4/test.conf b/testing/tests/swanctl/rw-psk-ipv4/test.conf
new file mode 100755
index 0000000..f292988
--- /dev/null
+++ b/testing/tests/swanctl/rw-psk-ipv4/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 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"
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 73646f8..2f104f5 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
@@ -2,5 +2,12 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
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 73646f8..2f104f5 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
@@ -2,5 +2,12 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
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 3975f09..51425ac 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
@@ -2,12 +2,18 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-11 tnc-imv updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
+      phase2_tnc_method = tnc
+    }
+    eap-tnc {
+      protocol = tnccs-1.1
     }
   }
 }
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 4cc205c..4c77038 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
@@ -2,7 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
 
 libimcv {
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 ac46959..df385d5 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
@@ -2,7 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
 
 libimcv {
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/hosts/alice/etc/pts/data1.sql b/testing/tests/tnc/tnccs-11-radius-pts/hosts/alice/etc/pts/data1.sql
index 2bb7e79..8b36df5 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/hosts/alice/etc/pts/data1.sql
+++ b/testing/tests/tnc/tnccs-11-radius-pts/hosts/alice/etc/pts/data1.sql
@@ -3,7 +3,7 @@
 INSERT INTO devices (                  /*  1 */
   value, product, created  
 ) VALUES (
-  'aabbccddeeff11223344556677889900', 28, 1372330615
+  'aabbccddeeff11223344556677889900', 42, 1372330615
 );
 
 /* Groups Members */
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 56c6b9f..4eeff49 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
@@ -2,7 +2,14 @@
 
 charon {
   load = curl openssl 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
+
   multiple_authentication=no
+
+  plugins {
+    eap-tnc {
+      protocol = tnccs-1.1
+    }
+  }
 }
 
 libimcv {
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 145ad9d..7c27dbd 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
@@ -2,7 +2,14 @@
 
 charon {
   load = curl openssl 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
+
   multiple_authentication=no
+
+  plugins {
+    eap-tnc {
+      protocol = tnccs-1.1
+    }
+  }
 }
 
 libimcv {
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 4cc205c..4c77038 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
@@ -2,7 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
 
 libimcv {
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 5dbee55..5424f4c 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
@@ -2,7 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
 
 libimcv {
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 4cc205c..4c77038 100644
--- a/testing/tests/tnc/tnccs-11/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11/hosts/carol/etc/strongswan.conf
@@ -2,7 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
 
 libimcv {
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 5dbee55..5424f4c 100644
--- a/testing/tests/tnc/tnccs-11/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11/hosts/dave/etc/strongswan.conf
@@ -2,7 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke 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
+    }
+  }
 }
 
 libimcv {
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 2fe4cf0..3037d00 100644
--- a/testing/tests/tnc/tnccs-11/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-11/hosts/moon/etc/strongswan.conf
@@ -2,12 +2,18 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-11 tnc-imv updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
+      phase2_tnc_method = tnc
+    }
+    eap-tnc {
+      protocol = tnccs-1.1
     }
   }
 }
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 ced332c..20c0928 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
@@ -2,11 +2,10 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = de, en
     }
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 70a1b07..64a25b4 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
@@ -2,11 +2,10 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+
   multiple_authentication=no
+
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = ru, fr, en
     }
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 59dce18..7ee2ead 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
@@ -2,16 +2,15 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imv {
       recommendation_policy = all
     }
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 f202bbf..c0e5e94 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
@@ -2,12 +2,8 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 996169a..4c31a78 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
@@ -2,11 +2,10 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = ru , de, en
     }
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 3e6bc65..46c7367 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
@@ -2,16 +2,15 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
   }
 }
 
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 18e7157..d71893a 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
@@ -2,10 +2,6 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
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 18e7157..d71893a 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
@@ -2,10 +2,6 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
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 602979c..7681388 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
@@ -2,15 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
   }
 }
diff --git a/testing/tests/tnc/tnccs-20-os-pts/description.txt b/testing/tests/tnc/tnccs-20-os-pts/description.txt
new file mode 100644
index 0000000..0ade4ba
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/description.txt
@@ -0,0 +1,22 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
+using EAP-TTLS authentication only with the gateway presenting a server certificate and
+the clients doing EAP-MD5 password-based authentication.
+In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
+state of <b>carol</b>'s and <b>dave</b>'s operating system via the <b>TNCCS 2.0 </b>
+client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The OS and Attestation IMCs
+exchange PA-TNC attributes with the OS and Attestation IMVs via the <b>IF-M 1.0</b> measurement
+protocol defined by <b>RFC 5792 PA-TNC</b>.
+<p>
+<b>carol</b> sends information on her operating system consisting of the PA-TNC attributes
+<em>Product Information</em>, <em>String Version</em>, and <em>Device ID</em> up-front
+to the Attestation IMV, whereas <b>dave</b> must be prompted by the IMV to do so via an
+<em>Attribute Request</em> PA-TNC attribute. <b>dave</b> is instructed to do a reference
+measurement on all files in the <b>/bin</b> directory. <b>carol</b> is then prompted to
+measure a couple of individual files and the files in the <b>/bin</b> directory as
+well as to get metadata on the <b>/etc/tnc_confg</b> configuration file.
+<p>
+<b>carol</b> passes the health test and <b>dave</b> fails because IP forwarding is
+enabled. Based on these assessments which are communicated to the IMCs using the
+<em>Assessment Result</em> PA-TNC attribute, the clients are connected by gateway <b>moon</b>
+to the "rw-allow" and "rw-isolate" subnets, respectively.
+</p>
diff --git a/testing/tests/tnc/tnccs-20-os-pts/evaltest.dat b/testing/tests/tnc/tnccs-20-os-pts/evaltest.dat
new file mode 100644
index 0000000..f9bb033
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/evaltest.dat
@@ -0,0 +1,20 @@
+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 7.5 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 7.5 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::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::ping -c 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 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
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
new file mode 100644
index 0000000..d17473d
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.conf
@@ -0,0 +1,23 @@
+# /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
new file mode 100644
index 0000000..74942af
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /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
new file mode 100644
index 0000000..f64fe6a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,15 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl openssl 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
+
+  multiple_authentication = no
+}
+
+libimcv {
+  plugins {
+    imc-os {
+      push_info = yes
+    }
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/tnc_config b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/tnc_config
new file mode 100644
index 0000000..15dc93a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/carol/etc/tnc_config
@@ -0,0 +1,4 @@
+#IMC configuration file for strongSwan client 
+
+IMC "OS"          /usr/local/lib/ipsec/imcvs/imc-os.so
+IMC "Attestation" /usr/local/lib/ipsec/imcvs/imc-attestation.so
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
new file mode 100644
index 0000000..d459bfc
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.conf
@@ -0,0 +1,23 @@
+# /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
new file mode 100644
index 0000000..5496df7
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /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
new file mode 100644
index 0000000..075919a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,21 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl openssl 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
+
+  multiple_authentication = no
+
+  plugins {
+    tnc-imc {
+      preferred_language = de
+    }
+  }
+}
+
+libimcv {
+  plugins {
+    imc-os {
+      push_info = no
+    }
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/tnc_config b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/tnc_config
new file mode 100644
index 0000000..15dc93a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/dave/etc/tnc_config
@@ -0,0 +1,4 @@
+#IMC configuration file for strongSwan client 
+
+IMC "OS"          /usr/local/lib/ipsec/imcvs/imc-os.so
+IMC "Attestation" /usr/local/lib/ipsec/imcvs/imc-attestation.so
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
new file mode 100644
index 0000000..bc8b2d8
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,34 @@
+# /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
new file mode 100644
index 0000000..2e277cc
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/ipsec.secrets
@@ -0,0 +1,6 @@
+# /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/pts/data1.sql b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/pts/data1.sql
new file mode 100644
index 0000000..8b36df5
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/pts/data1.sql
@@ -0,0 +1,29 @@
+/* Devices */
+
+INSERT INTO devices (                  /*  1 */
+  value, product, created  
+) VALUES (
+  'aabbccddeeff11223344556677889900', 42, 1372330615
+);
+
+/* Groups Members */
+
+INSERT INTO groups_members (
+  group_id, device_id
+) VALUES (
+  10, 1
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age, rec_fail, rec_noresult
+) VALUES (
+  3, 10, 0, 2, 2
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  16, 2, 0
+);
+
+DELETE FROM enforcements WHERE id = 1;
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
new file mode 100644
index 0000000..e81908f
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,31 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl openssl 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
+
+  multiple_authentication = no
+
+  plugins {
+    eap-ttls {
+      phase2_method = md5
+      phase2_piggyback = yes
+      phase2_tnc = yes
+    }
+  }
+}
+
+libimcv {
+  database = sqlite:///etc/pts/config.db
+  policy_script = ipsec imv_policy_manager
+  plugins {
+    imv-attestation {
+      hash_algorithm = sha1
+    }
+  }
+}
+
+attest {
+  load = random nonce openssl sqlite
+  database = sqlite:///etc/pts/config.db
+}
+
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/tnc_config b/testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/tnc_config
similarity index 100%
copy from testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/tnc_config
copy to testing/tests/tnc/tnccs-20-os-pts/hosts/moon/etc/tnc_config
diff --git a/testing/tests/tnc/tnccs-20-os-pts/posttest.dat b/testing/tests/tnc/tnccs-20-os-pts/posttest.dat
new file mode 100644
index 0000000..48514d6
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/posttest.dat
@@ -0,0 +1,8 @@
+moon::ipsec stop
+carol::ipsec stop
+dave::ipsec stop
+moon::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
+carol::echo 1 > /proc/sys/net/ipv4/ip_forward
+moon::rm /etc/pts/config.db
diff --git a/testing/tests/tnc/tnccs-20-os-pts/pretest.dat b/testing/tests/tnc/tnccs-20-os-pts/pretest.dat
new file mode 100644
index 0000000..49ea041
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/pretest.dat
@@ -0,0 +1,18 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+carol::echo 0 > /proc/sys/net/ipv4/ip_forward
+dave::echo aabbccddeeff11223344556677889900 > /var/lib/dbus/machine-id
+moon::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data.sql /etc/pts/data1.sql | sqlite3 /etc/pts/config.db
+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::sleep 1
+dave::ipsec up home
+carol::ipsec up home
+carol::sleep 1
+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
new file mode 100644
index 0000000..a8a05af
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-os-pts/test.conf
@@ -0,0 +1,26 @@
+#!/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"
+
+# Guest instances on which FreeRadius is started
+#
+RADIUSHOSTS=
+
diff --git a/testing/tests/tnc/tnccs-20-os/description.txt b/testing/tests/tnc/tnccs-20-os/description.txt
index 9411134..c4a2c90 100644
--- a/testing/tests/tnc/tnccs-20-os/description.txt
+++ b/testing/tests/tnc/tnccs-20-os/description.txt
@@ -1,12 +1,13 @@
 The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
 using EAP-TTLS authentication only with the gateway presenting a server certificate and
 the clients doing EAP-MD5 password-based authentication.
-In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
-state of <b>carol</b>'s and <b>dave</b>'s operating system via the <b>TNCCS 2.0 </b>
-client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The OS IMC and OS IMV pair
-is using the <b>IF-M 1.0</b> measurement protocol defined by <b>RFC 5792 PA-TNC</b> to
-exchange PA-TNC attributes.
-<p>
+<p/>
+In a next step the <b>RFC 7171 PT-EAP</b> transport protocol is used within the EAP-TTLS tunnel 
+to determine the state of <b>carol</b>'s and <b>dave</b>'s operating system via the <b>IF-TNCCS 2.0</b>
+client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The OS and Attestation IMCs
+exchange PA-TNC attributes with the OS IMV via the <b>IF-M 1.0</b> measurement protocol
+defined by <b>RFC 5792 PA-TNC</b>.
+<p/>
 <b>carol</b> sends information on her operating system consisting of the PA-TNC attributes
 <em>Product Information</em>, <em>String Version</em>, <em>Numeric Version</em>,
 <em>Operational Status</em>, <em>Forwarding Enabled</em>, <em>Factory Default Password Enabled</em>
diff --git a/testing/tests/tnc/tnccs-20-os/evaltest.dat b/testing/tests/tnc/tnccs-20-os/evaltest.dat
index 21a7278..b9f094f 100644
--- a/testing/tests/tnc/tnccs-20-os/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-os/evaltest.dat
@@ -6,10 +6,10 @@ dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::Y
 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 7.2 x86_64.*carol at strongswan.org - allow::YES
+moon:: ipsec attest --sessions 2> /dev/null::Debian 7.5 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 7.2 x86_64.*dave at strongswan.org - isolate::YES
+moon:: ipsec attest --sessions 2> /dev/null::Debian 7.5 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
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 34941e5..4f5993e 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
@@ -2,12 +2,8 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 49f778f..4ed358d 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
@@ -2,11 +2,10 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = de
     }
diff --git a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/pts/data1.sql b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/pts/data1.sql
index 6682a5a..6e7e10f 100644
--- a/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/pts/data1.sql
+++ b/testing/tests/tnc/tnccs-20-os/hosts/moon/etc/pts/data1.sql
@@ -3,7 +3,7 @@
 INSERT INTO devices (                  /*  1 */
   value, product, created  
 ) VALUES (
-  'aabbccddeeff11223344556677889900', 28, 1372330615
+  'aabbccddeeff11223344556677889900', 42, 1372330615
 );
 
 /* Groups Members */
@@ -27,7 +27,7 @@ INSERT INTO identities (
 INSERT INTO sessions (
   time, connection, identity, device, product, rec
 ) VALUES (
-  NOW, 1, 1, 1, 28, 0
+  NOW, 1, 1, 1, 42, 0
 );
 
 /* Results */
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 3e017e9..ed81c17 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
@@ -2,16 +2,15 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
   }
 }
 
diff --git a/testing/tests/tnc/tnccs-20-os/pretest.dat b/testing/tests/tnc/tnccs-20-os/pretest.dat
index 0ac88dd..d991ee3 100644
--- a/testing/tests/tnc/tnccs-20-os/pretest.dat
+++ b/testing/tests/tnc/tnccs-20-os/pretest.dat
@@ -15,6 +15,6 @@ carol::sleep 1
 carol::ipsec up home
 dave::ipsec up home
 dave::sleep 1
-moon::ipsec attest --packages --product 'Debian 7.2 x86_64'
+moon::ipsec attest --packages --product 'Debian 7.4 x86_64'
 moon::ipsec attest --sessions
 moon::ipsec attest --devices
diff --git a/testing/tests/tnc/tnccs-20-pdp/description.txt b/testing/tests/tnc/tnccs-20-pdp-eap/description.txt
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/description.txt
rename to testing/tests/tnc/tnccs-20-pdp-eap/description.txt
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat b/testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat
new file mode 100644
index 0000000..9a477bd
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/evaltest.dat
@@ -0,0 +1,29 @@
+dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA signature successful::YES
+dave:: cat /var/log/daemon.log::PDP server.*aaa.strongswan.org.*is listening on port 271::YES
+dave:: cat /var/log/daemon.log::collected 372 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 signature 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 373 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 372 SWID tags::YES
+alice::cat /var/log/daemon.log::user AR identity.*carol.*authenticated by password::YES
+alice::cat /var/log/daemon.log::IMV 2 handled SWIDT workitem 9: allow - received inventory of 373 SWID tag IDs and 1 SWID tag::YES
+moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'isolate'::YES
+moon:: cat /var/log/daemon.log::RADIUS authentication of 'dave' successful::YES
+moon:: cat /var/log/daemon.log::authentication of '192.168.0.200' with EAP successful::YES
+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::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+carol::ping -c 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 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/apache2/sites-available/default b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/apache2/sites-available/default
new file mode 100644
index 0000000..6260006
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/apache2/sites-available/default
@@ -0,0 +1,26 @@
+WSGIPythonPath /var/www/tnc
+
+<VirtualHost *:80>
+    ServerName tnc.strongswan.org
+    ServerAlias tnc
+    ServerAdmin webmaster at localhost
+
+    DocumentRoot /var/www/tnc
+
+    <Directory /var/www/tnc/config>
+        <Files wsgi.py>
+            Order deny,allow
+            Allow from all
+        </Files>
+    </Directory>
+
+    WSGIScriptAlias / /var/www/tnc/config/wsgi.py
+    WSGIApplicationGroup %{GLOBAL}
+    WSGIPassAuthorization On
+
+    Alias /static/ /var/www/tnc/static/
+
+    ErrorLog ${APACHE_LOG_DIR}/tnc/error.log
+    LogLevel warn
+    CustomLog ${APACHE_LOG_DIR}/tnc/access.log combined
+</VirtualHost>
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
new file mode 100644
index 0000000..f2e6119
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.conf
@@ -0,0 +1,9 @@
+# /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/hosts/alice/etc/ipsec.d/certs/aaaCert.pem b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.d/private/aaaKey.pem b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/private/aaaKey.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.d/private/aaaKey.pem
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.d/private/aaaKey.pem
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.secrets
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/ipsec.secrets
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/pts/data1.sql b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/pts/data1.sql
new file mode 100644
index 0000000..8adc459
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/pts/data1.sql
@@ -0,0 +1,61 @@
+/* Devices */
+
+INSERT INTO devices (                  /*  1 */
+  value, product, created  
+) VALUES (
+  'aabbccddeeff11223344556677889900', 42, 1372330615
+);
+
+/* Groups Members */
+
+INSERT INTO groups_members (
+  group_id, device_id
+) VALUES (
+  10, 1
+);
+
+/* Identities */
+
+INSERT INTO identities (
+  type, value
+) VALUES ( /* dave at strongswan.org */
+  5, X'64617665'
+);
+
+/* Sessions */
+
+INSERT INTO sessions (
+  time, connection, identity, device, product, rec
+) VALUES (
+  NOW, 1, 1, 1, 42, 0
+);
+
+/* Results */
+
+INSERT INTO results (
+  session, policy, rec, result
+) VALUES (
+  1, 1, 0, 'processed 355 packages: 0 not updated, 0 blacklisted, 4 ok, 351 not found'
+);
+
+/* Enforcements */
+
+INSERT INTO enforcements (
+  policy, group_id, max_age, rec_fail, rec_noresult
+) VALUES (
+  3, 10, 0, 2, 2
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  17, 2, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  18, 10, 86400
+);
+
+DELETE FROM enforcements WHERE id = 1;
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongTNC/settings.ini b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongTNC/settings.ini
new file mode 100644
index 0000000..5e7b7b5
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongTNC/settings.ini
@@ -0,0 +1,19 @@
+[debug]
+DEBUG=0
+TEMPLATE_DEBUG=0
+DEBUG_TOOLBAR=0
+
+[db]
+DJANGO_DB_URL=sqlite:////var/www/tnc/django.db
+STRONGTNC_DB_URL = sqlite:////etc/pts/config.db
+
+[localization]
+LANGUAGE_CODE=en-us
+TIME_ZONE=Europe/Zurich
+
+[admins]
+Your Name: alice at strongswan.org
+
+[security]
+SECRET_KEY=strongSwan
+ALLOWED_HOSTS=127.0.0.1,10.10.0.1,tnc.strongswan.org,tnc
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
new file mode 100644
index 0000000..a60f1de
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,35 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac socket-default kernel-netlink stroke eap-identity eap-ttls eap-md5 eap-tnc tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
+
+  plugins {
+    eap-ttls {
+      phase2_method = md5
+      phase2_piggyback = yes
+      phase2_tnc = yes
+      max_message_count = 0
+    }
+    eap-tnc {
+      max_message_count = 0
+    }
+    tnc-pdp {
+      server = aaa.strongswan.org
+      radius {
+        secret = gv6URkSs
+      }
+    }
+  }
+}
+
+libimcv {
+  debug_level = 3 
+  database = sqlite:///etc/pts/config.db
+  policy_script = ipsec imv_policy_manager
+
+  plugins {
+    imv-swid {
+      rest_api_uri = http://admin-user:strongSwan@tnc.strongswan.org/api/
+    }
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/tnc_config
similarity index 100%
copy from testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/tnc_config
copy to testing/tests/tnc/tnccs-20-pdp-eap/hosts/alice/etc/tnc_config
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
new file mode 100644
index 0000000..6e6430e
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.conf
@@ -0,0 +1,23 @@
+# /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/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.secrets
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/ipsec.secrets
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
new file mode 100644
index 0000000..c040f09
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,18 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+
+  plugins {
+    eap-ttls {
+      max_message_count = 0
+    }
+    eap-tnc {
+      max_message_count = 0
+    }
+    tnccs-20 {
+      max_batch_size = 32754
+      max_message_size = 32722
+    }
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/tnc_config
new file mode 100644
index 0000000..a954883
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/carol/etc/tnc_config
@@ -0,0 +1,4 @@
+#IMC configuration file for strongSwan client 
+
+IMC "OS"	/usr/local/lib/ipsec/imcvs/imc-os.so
+IMC "SWID"	/usr/local/lib/ipsec/imcvs/imc-swid.so
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
new file mode 100644
index 0000000..4846af2
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.conf
@@ -0,0 +1,23 @@
+# /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/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.secrets
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/ipsec.secrets
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
new file mode 100644
index 0000000..cd9efee
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,30 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
+
+  plugins {    
+   eap-ttls {
+      max_message_count = 0
+    }
+    eap-tnc {
+      max_message_count = 0
+    }
+    tnccs-20 {
+      max_batch_size = 32754
+      max_message_size = 32722
+    }
+  }
+}
+
+libimcv {
+  plugins {
+   imc-os {
+     push_info = no
+    }
+    imc-swid {
+      swid_directory = /usr/share
+      swid_pretty = no
+    }
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/tnc_config
new file mode 100644
index 0000000..a954883
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/dave/etc/tnc_config
@@ -0,0 +1,4 @@
+#IMC configuration file for strongSwan client 
+
+IMC "OS"	/usr/local/lib/ipsec/imcvs/imc-os.so
+IMC "SWID"	/usr/local/lib/ipsec/imcvs/imc-swid.so
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.conf
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.conf
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.conf
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.secrets
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/ipsec.secrets
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/iptables.rules b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/iptables.rules
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/iptables.rules
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/iptables.rules
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/strongswan.conf
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/strongswan.conf
rename to testing/tests/tnc/tnccs-20-pdp-eap/hosts/moon/etc/strongswan.conf
diff --git a/testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat b/testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat
new file mode 100644
index 0000000..1e5c3f8
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/posttest.dat
@@ -0,0 +1,9 @@
+moon::ipsec stop
+carol::ipsec stop
+dave::ipsec stop
+alice::ipsec stop
+alice::service apache2 stop
+alice::rm /etc/pts/config.db
+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
new file mode 100644
index 0000000..4ba63d1
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-eap/pretest.dat
@@ -0,0 +1,21 @@
+moon::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+alice::cat /etc/tnc_config
+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::sed -i "s/NOW/`date +%s`/g" /etc/pts/data1.sql
+alice::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data.sql /etc/pts/data1.sql | sqlite3 /etc/pts/config.db
+alice::chgrp www-data /etc/pts/config.db; chmod g+w /etc/pts/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
+carol::sleep 1
+dave::ipsec up home
+carol::ipsec up home
+carol::sleep 1
diff --git a/testing/tests/tnc/tnccs-20-pdp/test.conf b/testing/tests/tnc/tnccs-20-pdp-eap/test.conf
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pdp/test.conf
rename to testing/tests/tnc/tnccs-20-pdp-eap/test.conf
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/description.txt b/testing/tests/tnc/tnccs-20-pdp-pt-tls/description.txt
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/description.txt
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/description.txt
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat b/testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat
new file mode 100644
index 0000000..9327f51
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat
@@ -0,0 +1,19 @@
+dave:: cat /var/log/auth.log::sending TLS CertificateVerify handshake::YES
+dave:: cat /var/log/auth.log::collected 372 SWID tags::YES
+carol::cat /var/log/auth.log::received SASL Success result::YES
+carol::cat /var/log/auth.log::collected 373 SWID tag IDs::YES
+carol::cat /var/log/auth.log::collected 1 SWID tag::YES
+alice::cat /var/log/daemon.log::accepting PT-TLS stream from PH_IP_DAVE::YES
+alice::cat /var/log/daemon.log::checking certificate status of.*C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org::YES
+alice::cat /var/log/daemon.log::certificate status is good::YES
+alice::cat /var/log/daemon.log::skipping SASL, client already authenticated by TLS certificate::YES
+alice::cat /var/log/daemon.log::user AR identity.*C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org.*authenticated by certificate::YES
+alice::cat /var/log/daemon.log::received SWID tag inventory with 372 items for request 3 at eid 1 of epoch::YES
+alice::cat /var/log/daemon.log::accepting PT-TLS stream from PH_IP_CAROL::YES
+alice::cat /var/log/daemon.log::SASL PLAIN authentication successful::YES
+alice::cat /var/log/daemon.log::SASL client identity is.*carol::YES
+alice::cat /var/log/daemon.log::user AR identity.*carol.*authenticated by password::YES
+alice::cat /var/log/daemon.log::received SWID tag ID inventory with 373 items for request 9 at eid 1 of epoch::YES
+alice::cat /var/log/daemon.log::1 SWID tag target::YES
+alice::cat /var/log/daemon.log::received SWID tag inventory with 1 item for request 9 at eid 1 of epoch::YES
+alice::cat /var/log/daemon.log::regid.2004-03.org.strongswan_strongSwan-::YES
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/apache2/sites-available/default b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/apache2/sites-available/default
new file mode 100644
index 0000000..6260006
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/apache2/sites-available/default
@@ -0,0 +1,26 @@
+WSGIPythonPath /var/www/tnc
+
+<VirtualHost *:80>
+    ServerName tnc.strongswan.org
+    ServerAlias tnc
+    ServerAdmin webmaster at localhost
+
+    DocumentRoot /var/www/tnc
+
+    <Directory /var/www/tnc/config>
+        <Files wsgi.py>
+            Order deny,allow
+            Allow from all
+        </Files>
+    </Directory>
+
+    WSGIScriptAlias / /var/www/tnc/config/wsgi.py
+    WSGIApplicationGroup %{GLOBAL}
+    WSGIPassAuthorization On
+
+    Alias /static/ /var/www/tnc/static/
+
+    ErrorLog ${APACHE_LOG_DIR}/tnc/error.log
+    LogLevel warn
+    CustomLog ${APACHE_LOG_DIR}/tnc/access.log combined
+</VirtualHost>
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
new file mode 100644
index 0000000..7b2118f
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.conf
@@ -0,0 +1,9 @@
+# /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-pt-tls/hosts/alice/etc/ipsec.d/certs/aaaCert.pem b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/certs/aaaCert.pem
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.d/private/aaaKey.pem b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/private/aaaKey.pem
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.d/private/aaaKey.pem
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.d/private/aaaKey.pem
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.secrets
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/ipsec.secrets
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/iptables.rules b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/iptables.rules
new file mode 100644
index 0000000..1586214
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/iptables.rules
@@ -0,0 +1,24 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# open loopback interface
+-A INPUT  -i lo -j ACCEPT
+-A OUTPUT -o lo -j ACCEPT
+
+# allow PT-TLS 
+-A INPUT  -i eth0 -p tcp --dport 271 -j ACCEPT
+-A OUTPUT -o eth0 -p tcp --sport 271 -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 192.168.0.150 -j ACCEPT
+-A OUTPUT -o eth0 -p tcp --dport 80 -d 192.168.0.150 -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/pts/data1.sql b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/pts/data1.sql
new file mode 100644
index 0000000..14f9d7d
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/pts/data1.sql
@@ -0,0 +1,61 @@
+/* Devices */
+
+INSERT INTO devices (                  /*  1 */
+  value, product, created  
+) VALUES (
+  'aabbccddeeff11223344556677889900', 42, 1372330615
+);
+
+/* Groups Members */
+
+INSERT INTO groups_members (
+  group_id, device_id
+) VALUES (
+  10, 1
+);
+
+/* Identities */
+
+INSERT INTO identities (
+  type, value
+) VALUES ( /* dave at strongswan.org */
+  4, X'64617665407374726f6e677377616e2e6f7267'
+);
+
+/* Sessions */
+
+INSERT INTO sessions (
+  time, connection, identity, device, product, rec
+) VALUES (
+  NOW, 1, 1, 1, 42, 0
+);
+
+/* Results */
+
+INSERT INTO results (
+  session, policy, rec, result
+) VALUES (
+  1, 1, 0, 'processed 355 packages: 0 not updated, 0 blacklisted, 4 ok, 351 not found'
+);
+
+/* Enforcements */
+
+INSERT INTO enforcements (
+  policy, group_id, max_age, rec_fail, rec_noresult
+) VALUES (
+  3, 10, 0, 2, 2
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  17, 2, 86400
+);
+
+INSERT INTO enforcements (
+  policy, group_id, max_age
+) VALUES (
+  18, 10, 86400
+);
+
+DELETE FROM enforcements WHERE id = 1;
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongTNC/settings.ini b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongTNC/settings.ini
new file mode 100644
index 0000000..5e7b7b5
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongTNC/settings.ini
@@ -0,0 +1,19 @@
+[debug]
+DEBUG=0
+TEMPLATE_DEBUG=0
+DEBUG_TOOLBAR=0
+
+[db]
+DJANGO_DB_URL=sqlite:////var/www/tnc/django.db
+STRONGTNC_DB_URL = sqlite:////etc/pts/config.db
+
+[localization]
+LANGUAGE_CODE=en-us
+TIME_ZONE=Europe/Zurich
+
+[admins]
+Your Name: alice at strongswan.org
+
+[security]
+SECRET_KEY=strongSwan
+ALLOWED_HOSTS=127.0.0.1,10.10.0.1,tnc.strongswan.org,tnc
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
new file mode 100644
index 0000000..eb807b1
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,29 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = curl pem pkcs1 nonce x509 revocation constraints openssl socket-default kernel-netlink stroke tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
+
+  plugins { 
+    tnc-pdp {
+      server = aaa.strongswan.org
+      radius {
+        secret = gv6URkSs
+      }
+    }
+  }
+}
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+}
+
+libimcv {
+  database = sqlite:///etc/pts/config.db
+  policy_script = ipsec imv_policy_manager
+
+  plugins {
+    imv-swid {
+      rest_api_uri = http://admin-user:strongSwan@tnc.strongswan.org/api/
+    }
+  }
+}
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/tnc_config
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/tnc_config
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/tnc_config
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.conf
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/ipsec.conf
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.conf
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/ipsec.secrets
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.secrets
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/ipsec.sql b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.sql
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/ipsec.sql
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/ipsec.sql
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/iptables.rules b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/iptables.rules
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/iptables.rules
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/iptables.rules
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
new file mode 100644
index 0000000..d485e9b
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/pts/options
@@ -0,0 +1,6 @@
+--connect aaa.strongswan.org
+--client carol
+--secret "Ar3etTnp"
+--cert /etc/ipsec.d/cacerts/strongswanCert.pem
+--quiet
+--debug 2
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..29fdf02
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,9 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+}
+
+pt-tls-client {
+  load = curl revocation constraints pem openssl nonce tnc-tnccs tnc-imc tnccs-20
+}
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/tnc_config
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/tnc_config
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/carol/etc/tnc_config
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.conf
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/ipsec.conf
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.conf
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.secrets
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/ipsec.secrets
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.secrets
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/ipsec.sql b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.sql
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/ipsec.sql
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/ipsec.sql
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/iptables.rules b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/iptables.rules
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/iptables.rules
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/iptables.rules
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
new file mode 100644
index 0000000..ca3ca3a
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/pts/options
@@ -0,0 +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
+--quiet
+--debug 2
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/strongswan.conf
new file mode 100644
index 0000000..0a7f048
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,21 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+libimcv {
+  plugins {
+    imc-os {
+      push_info = no
+    }
+    imc-swid {
+      swid_directory = /usr/share
+      swid_pretty = yes
+    }
+  }
+}
+
+libtls {
+  suites = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+}
+
+pt-tls-client {
+  load = curl revocation constraints pem openssl nonce tnc-tnccs tnc-imc tnccs-20
+}
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/tnc_config
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/tnc_config
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/dave/etc/tnc_config
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat b/testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat
new file mode 100644
index 0000000..b7da857
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/posttest.dat
@@ -0,0 +1,9 @@
+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 apache2 stop
+alice::rm /etc/pts/config.db
+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
new file mode 100644
index 0000000..ca8f47d
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/pretest.dat
@@ -0,0 +1,23 @@
+alice::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+alice::cat /etc/tnc_config
+carol::cat /etc/tnc_config
+carol::echo 0 > /proc/sys/net/ipv4/ip_forward
+dave::echo aabbccddeeff11223344556677889900 > /var/lib/dbus/machine-id
+dave::cat /etc/tnc_config
+alice::sed -i "s/NOW/`date +%s`/g" /etc/pts/data1.sql
+alice::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data.sql /etc/pts/data1.sql | sqlite3 /etc/pts/config.db
+alice::chgrp www-data /etc/pts/config.db; chmod g+w /etc/pts/config.db
+alice::/var/www/tnc/manage.py setpassword strongSwan strongSwan
+alice::service apache2 start
+alice::ipsec start
+alice::sleep 1
+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
+dave::cat /etc/pts/options
+dave::ipsec pt-tls-client --optionsfrom /etc/pts/options
+carol::ip route add 10.1.0.0/16 via 192.168.0.1
+carol::cat /etc/pts/options
+carol::ipsec pt-tls-client --optionsfrom /etc/pts/options
+carol::sleep 1
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/test.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
similarity index 100%
rename from testing/tests/tnc/tnccs-20-pt-tls/test.conf
rename to testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
diff --git a/testing/tests/tnc/tnccs-20-pdp/evaltest.dat b/testing/tests/tnc/tnccs-20-pdp/evaltest.dat
deleted file mode 100644
index 505a4d0..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/evaltest.dat
+++ /dev/null
@@ -1,22 +0,0 @@
-carol::cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA signature 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::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
-dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with RSA signature successful::YES
-dave:: cat /var/log/daemon.log::PDP server.*aaa.strongswan.org.*is listening on port 271::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
-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:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'isolate'::YES
-moon:: cat /var/log/daemon.log::RADIUS authentication of 'dave' successful::YES
-moon:: cat /var/log/daemon.log::authentication of '192.168.0.200' 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::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
-carol::ping -c 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 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.conf
deleted file mode 100644
index 6f673dc..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-# /etc/ipsec.conf - strongSwan IPsec configuration file
-
-config setup
-	charondebug="tnc 3, imv 3"
-
-conn aaa
-	leftcert=aaaCert.pem
-	leftid=aaa.strongswan.org
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/strongswan.conf
deleted file mode 100644
index ec4956c..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/strongswan.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac socket-default kernel-netlink stroke eap-identity eap-ttls eap-md5 eap-tnc tnc-pdp tnc-imv tnc-tnccs tnccs-20
-  plugins {
-    eap-ttls {
-      phase2_method = md5
-      phase2_piggyback = yes
-      phase2_tnc = yes
-    }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-    tnc-pdp {
-      server = aaa.strongswan.org
-      radius {
-        secret = gv6URkSs
-      }
-    }
-  }
-}
-
-libimcv {
-  debug_level = 3 
-  plugins {
-    imv-test {
-      rounds = 1 
-    }
-  }
-}
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/tnc_config
deleted file mode 100644
index da732f6..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/tnc_config
+++ /dev/null
@@ -1,4 +0,0 @@
-#IMV configuration file for strongSwan client 
-
-IMV "Test"	/usr/local/lib/ipsec/imcvs/imv-test.so
-IMV "Scanner"	/usr/local/lib/ipsec/imcvs/imv-scanner.so
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.conf
deleted file mode 100644
index 5956373..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/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
-	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/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/strongswan.conf
deleted file mode 100644
index 808f1d1..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/strongswan.conf
+++ /dev/null
@@ -1,18 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
-}
-
-libimcv {
-  plugins {
-    imc-test {
-      command = allow
-    }
-  }
-}
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/tnc_config
deleted file mode 100644
index 6166552..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/tnc_config
+++ /dev/null
@@ -1,4 +0,0 @@
-#IMC configuration file for strongSwan client 
-
-IMC "Test"	/usr/local/lib/ipsec/imcvs/imc-test.so
-IMC "Scanner"	/usr/local/lib/ipsec/imcvs/imc-scanner.so
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.conf
deleted file mode 100644
index 8c27c78..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/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
-	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/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/strongswan.conf
deleted file mode 100644
index 96ff63a..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/strongswan.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  plugins {    
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
-}
-
-libimcv {
-  plugins {
-    imc-test {
-      command = isolate
-    }
-    imc-scannner {
-      push_info = no
-    }
-  }
-}
diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/tnc_config b/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/tnc_config
deleted file mode 100644
index 6166552..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/tnc_config
+++ /dev/null
@@ -1,4 +0,0 @@
-#IMC configuration file for strongSwan client 
-
-IMC "Test"	/usr/local/lib/ipsec/imcvs/imc-test.so
-IMC "Scanner"	/usr/local/lib/ipsec/imcvs/imc-scanner.so
diff --git a/testing/tests/tnc/tnccs-20-pdp/posttest.dat b/testing/tests/tnc/tnccs-20-pdp/posttest.dat
deleted file mode 100644
index e7eecd5..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/posttest.dat
+++ /dev/null
@@ -1,7 +0,0 @@
-moon::ipsec stop
-carol::ipsec stop
-dave::ipsec stop
-alice::ipsec 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-pdp/pretest.dat b/testing/tests/tnc/tnccs-20-pdp/pretest.dat
deleted file mode 100644
index 32ed4d8..0000000
--- a/testing/tests/tnc/tnccs-20-pdp/pretest.dat
+++ /dev/null
@@ -1,14 +0,0 @@
-moon::iptables-restore < /etc/iptables.rules
-carol::iptables-restore < /etc/iptables.rules
-dave::iptables-restore < /etc/iptables.rules
-alice::cat /etc/tnc_config
-carol::cat /etc/tnc_config
-dave::cat /etc/tnc_config
-alice::ipsec start
-moon::ipsec start
-carol::ipsec start
-dave::ipsec start
-carol::sleep 1
-carol::ipsec up home
-dave::ipsec up home
-dave::sleep 1
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/evaltest.dat b/testing/tests/tnc/tnccs-20-pt-tls/evaltest.dat
deleted file mode 100644
index 3139ca0..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/evaltest.dat
+++ /dev/null
@@ -1,12 +0,0 @@
-alice:: cat /var/log/daemon.log::accepting PT-TLS stream from PH_IP_CAROL::YES
-alice:: cat /var/log/daemon.log::SASL PLAIN authentication successful::YES
-alice:: cat /var/log/daemon.log::SASL client identity is.*carol::YES
-alice:: cat /var/log/daemon.log::user AR identity.*carol.*authenticated by password::YES
-alice:: cat /var/log/daemon.log::received SWID tag ID inventory for request 6 at eid 1 of epoch::YES
-alice:: cat /var/log/daemon.log::regid.2004-03.org.strongswan_strongSwan-.*.swidtag::YES
-alice:: cat /var/log/daemon.log::accepting PT-TLS stream from PH_IP_DAVE::YES
-alice:: cat /var/log/daemon.log::checking certificate status of.*C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org::YES
-alice:: cat /var/log/daemon.log::certificate status is good::YES
-alice:: cat /var/log/daemon.log::skipping SASL, client already authenticated by TLS certificate::YES
-alice:: cat /var/log/daemon.log::user AR identity.*C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org.*authenticated by certificate::YES
-alice:: cat /var/log/daemon.log::received SWID tag inventory for request 11 at eid 1 of epoch::YES
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/ipsec.conf
deleted file mode 100644
index d8b8433..0000000
--- a/testing/tests/tnc/tnccs-20-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 3, imv 3"
-
-conn aaa
-	leftcert=aaaCert.pem
-	leftid=aaa.strongswan.org
-	auto=add
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/iptables.rules b/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/iptables.rules
deleted file mode 100644
index 5b27539..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/iptables.rules
+++ /dev/null
@@ -1,20 +0,0 @@
-*filter
-
-# default policy is DROP
--P INPUT DROP
--P OUTPUT DROP
--P FORWARD DROP
-
-# allow PT-TLS 
--A INPUT  -i eth0 -p tcp --dport 271 -j ACCEPT
--A OUTPUT -o eth0 -p tcp --sport 271 -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 192.168.0.150 -j ACCEPT
--A OUTPUT -o eth0 -p tcp --dport 80 -d 192.168.0.150 -j ACCEPT
-
-COMMIT
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/pts/data1.sql b/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/pts/data1.sql
deleted file mode 100644
index 7159221..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/pts/data1.sql
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Devices */
-
-INSERT INTO devices (                  /*  1 */
-  value, product, created  
-) VALUES (
-  'aabbccddeeff11223344556677889900', 28, 1372330615
-);
-
-/* Groups Members */
-
-INSERT INTO groups_members (
-  group_id, device_id
-) VALUES (
-  10, 1
-);
-
-/* Identities */
-
-INSERT INTO identities (
-  type, value
-) VALUES ( /* dave at strongswan.org */
-  4, X'64617665407374726f6e677377616e2e6f7267'
-);
-
-/* Sessions */
-
-INSERT INTO sessions (
-  time, connection, identity, device, product, rec
-) VALUES (
-  NOW, 1, 1, 1, 28, 0
-);
-
-/* Results */
-
-INSERT INTO results (
-  session, policy, rec, result
-) VALUES (
-  1, 1, 0, 'processed 355 packages: 0 not updated, 0 blacklisted, 4 ok, 351 not found'
-);
-
-/* Enforcements */
-
-INSERT INTO enforcements (
-  policy, group_id, max_age, rec_fail, rec_noresult
-) VALUES (
-  3, 10, 0, 2, 2
-);
-
-INSERT INTO enforcements (
-  policy, group_id, max_age
-) VALUES (
-  17, 2, 86400
-);
-
-INSERT INTO enforcements (
-  policy, group_id, max_age
-) VALUES (
-  18, 10, 86400
-);
-
-DELETE FROM enforcements WHERE id = 1;
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/strongswan.conf
deleted file mode 100644
index 21961d4..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/hosts/alice/etc/strongswan.conf
+++ /dev/null
@@ -1,28 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-charon {
-  load = curl pem pkcs1 nonce x509 revocation constraints openssl socket-default kernel-netlink stroke tnc-pdp tnc-imv tnc-tnccs tnccs-20 sqlite
-
-  plugins { 
-    tnc-pdp {
-      server = aaa.strongswan.org
-      radius {
-        secret = gv6URkSs
-      }
-    }
-  }
-}
-
-libtnccs {
-  plugins {
-    tnccs-20 {
-      max_batch_size = 131056
-      max_message_size = 131024
-    }
-  }
-}
-
-libimcv {
-  database = sqlite:///etc/pts/config.db
-  policy_script = ipsec imv_policy_manager
-}
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/pts/options b/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/pts/options
deleted file mode 100644
index f04e947..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/pts/options
+++ /dev/null
@@ -1,5 +0,0 @@
---connect aaa.strongswan.org
---client carol
---secret "Ar3etTnp"
---cert /etc/ipsec.d/cacerts/strongswanCert.pem
---debug 2 
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/strongswan.conf
deleted file mode 100644
index de2fea2..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/hosts/carol/etc/strongswan.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-libimcv {
-  plugins {
-    imc-os {
-      push_info = yes 
-    }
-    imc-swid {
-      #swid_directory = /usr/share
-    }
-  }
-}
-
-libtnccs {
-  plugins {
-    tnccs-20 {
-      max_batch_size   = 131056
-      max_message_size = 131024
-    }
-  }
-}
-
-pt-tls-client {
-  load = curl revocation constraints pem openssl nonce tnc-tnccs tnc-imc tnccs-20
-}
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/pts/options b/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/pts/options
deleted file mode 100644
index 46821ec..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/pts/options
+++ /dev/null
@@ -1,6 +0,0 @@
---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
---debug 2
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/strongswan.conf
deleted file mode 100644
index 39b2577..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/hosts/dave/etc/strongswan.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-# /etc/strongswan.conf - strongSwan configuration file
-
-libimcv {
-  plugins {
-    imc-os {
-      push_info = no
-    }
-  }
-}
-
-libtnccs {
-  plugins {
-    tnccs-20 {
-      max_batch_size   = 131056
-      max_message_size = 131024
-    }
-  }
-}
-
-pt-tls-client {
-  load = curl revocation constraints pem openssl nonce tnc-tnccs tnc-imc tnccs-20
-}
diff --git a/testing/tests/tnc/tnccs-20-pt-tls/posttest.dat b/testing/tests/tnc/tnccs-20-pt-tls/posttest.dat
deleted file mode 100644
index c98df86..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/posttest.dat
+++ /dev/null
@@ -1,8 +0,0 @@
-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::rm /etc/pts/config.db
-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-pt-tls/pretest.dat b/testing/tests/tnc/tnccs-20-pt-tls/pretest.dat
deleted file mode 100644
index 97ff0c1..0000000
--- a/testing/tests/tnc/tnccs-20-pt-tls/pretest.dat
+++ /dev/null
@@ -1,19 +0,0 @@
-alice::iptables-restore < /etc/iptables.rules
-carol::iptables-restore < /etc/iptables.rules
-dave::iptables-restore < /etc/iptables.rules
-alice::cat /etc/tnc_config
-carol::cat /etc/tnc_config
-carol::echo 0 > /proc/sys/net/ipv4/ip_forward
-dave::echo aabbccddeeff11223344556677889900 > /var/lib/dbus/machine-id
-dave::cat /etc/tnc_config
-alice::sed -i "s/NOW/`date +%s`/g" /etc/pts/data1.sql
-alice::cd /usr/local/share/strongswan/templates/database/imv; cat tables.sql data.sql /etc/pts/data1.sql | sqlite3 /etc/pts/config.db
-alice::ipsec start
-winnetou::ip route add 10.1.0.0/16 via 192.168.0.1
-carol::ip route add 10.1.0.0/16 via 192.168.0.1
-carol::cat /etc/pts/options
-carol::ipsec pt-tls-client --optionsfrom /etc/pts/options
-dave::ip route add 10.1.0.0/16 via 192.168.0.1
-dave::cat /etc/pts/options
-dave::ipsec pt-tls-client --optionsfrom /etc/pts/options
-dave::sleep 1
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/description.txt b/testing/tests/tnc/tnccs-20-pts-no-ecc/description.txt
index 2997650..febf074 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/description.txt
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/description.txt
@@ -1,12 +1,13 @@
 The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
 using EAP-TTLS authentication only with the gateway presenting a server certificate and
 the clients doing EAP-MD5 password-based authentication.
-In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
-state of <b>carol</b>'s and <b>dave</b>'s operating system via the <b>TNCCS 2.0 </b>
-client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The OS IMC and OS IMV pair
-is using the <b>IF-M 1.0</b> measurement protocol defined by <b>RFC 5792 PA-TNC</b> to
-exchange PA-TNC attributes.
-<p>
+<p/>
+In a next step the <b>RFC 7171 PT-EAP</b> transport protocol is used within the EAP-TTLS 
+tunnel to determine the state of <b>carol</b>'s and <b>dave</b>'s operating system via the 
+<b>TNCCS 2.0 </b> client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The OS IMC 
+and OS IMV pair is using the <b>IF-M 1.0</b> measurement protocol defined by <b>RFC 5792 PA-TNC</b> 
+to exchange PA-TNC attributes.
+<p/>
 <b>carol</b> sends information on her operating system consisting of the PA-TNC attributes
 <em>Product Information</em>, <em>String Version</em>, and <em>Device ID</em> up-front
 to the Attestation IMV, whereas <b>dave</b> must be prompted by the IMV to do so via an
@@ -14,7 +15,7 @@ to the Attestation IMV, whereas <b>dave</b> must be prompted by the IMV to do so
 measurement on all files in the <b>/bin</b> directory. <b>carol</b> is then prompted to
 measure a couple of individual files and the files in the <b>/bin</b> directory as
 well as to get metadata on the <b>/etc/tnc_confg</b> configuration file.
-<p>
+<p/>
 Since the Attestation IMV negotiates a Diffie-Hellman group for TPM-based measurements,
 the mandatory default being <b>ecp256</b>, with the strongswan.conf option
 <b>mandatory_dh_groups = no</b> no ECC support is required.
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 5eb9440..f9bb033 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/evaltest.dat
@@ -6,10 +6,10 @@ dave:: cat /var/log/daemon.log::PB-TNC access recommendation is 'Quarantined'::Y
 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 7.2 x86_64.*carol at strongswan.org - allow::YES
+moon:: ipsec attest --session 2> /dev/null::Debian 7.5 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 7.2 x86_64.*dave at strongswan.org - isolate::YES
+moon:: ipsec attest --session 2> /dev/null::Debian 7.5 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
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 72bf2c7..53bb9df 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
@@ -2,12 +2,8 @@
 
 charon {
   load = curl aes md5 sha1 sha2 hmac gmp pem pkcs1 random nonce x509 revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 6f71994..25c27be 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
@@ -2,11 +2,10 @@
 
 charon {
   load = curl aes md5 sha1 sha2 hmac gmp pem pkcs1 random nonce x509 revocation stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = de
     }
diff --git a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/pts/data1.sql b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/pts/data1.sql
index 2bb7e79..8b36df5 100644
--- a/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/pts/data1.sql
+++ b/testing/tests/tnc/tnccs-20-pts-no-ecc/hosts/moon/etc/pts/data1.sql
@@ -3,7 +3,7 @@
 INSERT INTO devices (                  /*  1 */
   value, product, created  
 ) VALUES (
-  'aabbccddeeff11223344556677889900', 28, 1372330615
+  'aabbccddeeff11223344556677889900', 42, 1372330615
 );
 
 /* Groups Members */
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 e76598b..07d620c 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
@@ -2,16 +2,15 @@
 
 charon {
   load = curl aes md5 sha1 sha2 hmac gmp pem pkcs1 random nonce x509 revocation stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown sqlite
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
   }
 }
 
diff --git a/testing/tests/tnc/tnccs-20-pts/description.txt b/testing/tests/tnc/tnccs-20-pts/description.txt
index e78a700..e532ab2 100644
--- a/testing/tests/tnc/tnccs-20-pts/description.txt
+++ b/testing/tests/tnc/tnccs-20-pts/description.txt
@@ -1,12 +1,13 @@
 The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
 using EAP-TTLS authentication only with the gateway presenting a server certificate and
 the clients doing EAP-MD5 password-based authentication.
-In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
-state of <b>carol</b>'s and <b>dave</b>'s operating system via the <b>TNCCS 2.0 </b>
-client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The OS IMC and OS IMV pair
-is using the <b>IF-M 1.0</b> measurement protocol defined by <b>RFC 5792 PA-TNC</b> to
-exchange PA-TNC attributes.
-<p>
+<p/>
+In a next step the <b>RFC 7171 PT-EAP</b> transport protocol is used within the EAP-TTLS tunnel 
+to determine the state of <b>carol</b>'s and <b>dave</b>'s operating system via the <b>TNCCS 2.0</b>
+client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The OS and Attestation IMCs
+exchange PA-TNC attributes with the OS IMV via the <b>IF-M 1.0</b> measurement protocol
+defined by <b>RFC 5792 PA-TNC</b>.
+<p/>
 <b>carol</b> sends information on her operating system consisting of the PA-TNC attributes
 <em>Product Information</em>, <em>String Version</em>, and <em>Device ID</em> up-front
 to the Attestation IMV, whereas <b>dave</b> must be prompted by the IMV to do so via an
diff --git a/testing/tests/tnc/tnccs-20-pts/evaltest.dat b/testing/tests/tnc/tnccs-20-pts/evaltest.dat
index 5eb9440..2d18138 100644
--- a/testing/tests/tnc/tnccs-20-pts/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-pts/evaltest.dat
@@ -2,19 +2,19 @@ carol::cat /var/log/daemon.log::PB-TNC access recommendation is 'Access Allowed'
 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 '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.16/28::YES
-moon:: ipsec attest --session 2> /dev/null::Debian 7.2 x86_64.*carol at strongswan.org - allow::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 7.5 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 7.2 x86_64.*dave at strongswan.org - isolate::YES
-moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES
+moon:: ipsec attest --session 2> /dev/null::Debian 7.5 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-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.200/32::YES
 carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
 carol::ping -c 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 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
+dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
+dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::NO
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 e604683..f64fe6a 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
@@ -2,12 +2,8 @@
 
 charon {
   load = curl openssl 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
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 3236a18..79c79b8 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
@@ -2,11 +2,9 @@
 
 charon {
   load = curl openssl 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
-  multiple_authentication=no
+
+  multiple_authentication = no
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = de
     }
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/pts/data1.sql b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/pts/data1.sql
index 2bb7e79..8b36df5 100644
--- a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/pts/data1.sql
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/pts/data1.sql
@@ -3,7 +3,7 @@
 INSERT INTO devices (                  /*  1 */
   value, product, created  
 ) VALUES (
-  'aabbccddeeff11223344556677889900', 28, 1372330615
+  'aabbccddeeff11223344556677889900', 42, 1372330615
 );
 
 /* Groups Members */
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 0298a51..e81908f 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
@@ -2,16 +2,15 @@
 
 charon {
   load = curl openssl 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
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
   }
 }
 
diff --git a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/tnc_config b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/tnc_config
index 6507baa..4865036 100644
--- a/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/tnc_config
+++ b/testing/tests/tnc/tnccs-20-pts/hosts/moon/etc/tnc_config
@@ -1,4 +1,3 @@
 #IMV configuration file for strongSwan client 
 
-IMV "OS"          /usr/local/lib/ipsec/imcvs/imv-os.so
 IMV "Attestation" /usr/local/lib/ipsec/imcvs/imv-attestation.so
diff --git a/testing/tests/tnc/tnccs-20-server-retry/description.txt b/testing/tests/tnc/tnccs-20-server-retry/description.txt
index b37fbd4..f9ee7b8 100644
--- a/testing/tests/tnc/tnccs-20-server-retry/description.txt
+++ b/testing/tests/tnc/tnccs-20-server-retry/description.txt
@@ -1,10 +1,11 @@
 The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
 using EAP-TTLS authentication only with the gateway presenting a server certificate and
 the clients doing EAP-MD5 password-based authentication.
-In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
-health of <b>carol</b> and <b>dave</b> via the <b>TNCCS 2.0 </b> client-server interface
-compliant with <b>RFC 5793 PB-TNC</b>. The IMC and IMV communicate are using the <b>IF-M</b>
-protocol defined by <b>RFC 5792 PA-TNC</b>.
+<p/>
+In a next step the <b>RFC 7171 PT-EAP</b> transport protocol is used within the EAP-TTLS
+tunnel to determine the health of <b>carol</b> and <b>dave</b> via the <b>IF-TNCCS 2.0 </b>
+client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The IMCs and IMVs exchange
+messages over the <b>IF-M</b> protocol defined by <b>RFC 5792 PA-TNC</b>.
 <p>
 The first time the TNC clients <b>carol</b> and <b>dave</b> send their measurements,
 TNC server <b>moon</b> requests a handshake retry. In the retry <b>carol</b> succeeds
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 6f145ab..5e661c3 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
@@ -2,12 +2,8 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 fce9499..6b86fe8 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
@@ -2,11 +2,10 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = ru , de, en
     }
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 3e6bc65..46c7367 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
@@ -2,16 +2,15 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
   }
 }
 
diff --git a/testing/tests/tnc/tnccs-20-tls/description.txt b/testing/tests/tnc/tnccs-20-tls/description.txt
index a032d2d..f193bd2 100644
--- a/testing/tests/tnc/tnccs-20-tls/description.txt
+++ b/testing/tests/tnc/tnccs-20-tls/description.txt
@@ -1,9 +1,10 @@
 The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>,
 both ends doing certificate-based EAP-TLS authentication only.
-In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
-health of <b>carol</b> and <b>dave</b> via the <b>IF-TNCCS 2.0 </b> client-server interface
-compliant with <b>RFC 5793 PB-TNC</b>. The IMC and IMV communicate are using the <b>IF-M</b>
-protocol defined by <b>RFC 5792 PA-TNC</b>.
+<p/>
+In a next step the <b>RFC 7171 PT-EAP</b> transport protocol is used within the EAP-TTLS
+tunnel to determine the health of <b>carol</b> and <b>dave</b> via the <b>IF-TNCCS 2.0 </b>
+client-server interface compliant with <b>RFC 5793 PB-TNC</b>. The IMCs and IMVs exchange
+messages over the <b>IF-M</b> protocol defined by <b>RFC 5792 PA-TNC</b>.
 <p>
 <b>carol</b> passes the health test and <b>dave</b> fails. Based on these measurements the
 clients are connected by gateway <b>moon</b> to the "rw-allow" and "rw-isolate" subnets,
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 ada13a3..1cf2f0e 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
@@ -2,12 +2,8 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 0870ca6..0e63eab 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
@@ -2,12 +2,8 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 bc1d421..1a4dc85 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
@@ -2,25 +2,14 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-tnccs tnccs-20 tnc-imv updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       request_peer_auth = yes
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
-}
-
-libimcv {
-  plugins {
-    imv-scanner {
-      closed_port_policy = no
-      tcp_ports = 80 443
-      udp_ports =
-    }
   }
 }
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 6d8c10e..292bfa5 100644
--- a/testing/tests/tnc/tnccs-20/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20/hosts/carol/etc/strongswan.conf
@@ -2,12 +2,8 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-tnccs tnc-imc tnccs-20 updown
-  multiple_authentication=no
-  plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
-  }
+
+  multiple_authentication = no
 }
 
 libimcv {
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 1e5f50b..75f6d73 100644
--- a/testing/tests/tnc/tnccs-20/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20/hosts/dave/etc/strongswan.conf
@@ -2,11 +2,10 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-md5 eap-ttls eap-tnc tnc-imc tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
     tnc-imc {
       preferred_language = ru, pl  , de
     }
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 1a0cc20..94e1ee9 100644
--- a/testing/tests/tnc/tnccs-20/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20/hosts/moon/etc/strongswan.conf
@@ -2,16 +2,15 @@
 
 charon {
   load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-ttls eap-md5 eap-tnc tnc-imv tnc-tnccs tnccs-20 updown
-  multiple_authentication=no
+
+  multiple_authentication = no
+
   plugins {
     eap-ttls {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
     }
-    eap-tnc {
-      protocol = tnccs-2.0
-    }
   }
 }
 
diff --git a/testing/tests/tnc/tnccs-dynamic/description.txt b/testing/tests/tnc/tnccs-dynamic/description.txt
index 21e9bc6..86f6323 100644
--- a/testing/tests/tnc/tnccs-dynamic/description.txt
+++ b/testing/tests/tnc/tnccs-dynamic/description.txt
@@ -1,6 +1,7 @@
 The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>
 using EAP-TTLS authentication only with the gateway presenting a server certificate and
 the clients doing EAP-MD5 password-based authentication.
+<p/>
 In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
 health of TNC client <b>carol</b> via the <b>TNCCS 1.1 </b> client-server interface and of
 TNC client <b>dave</b> via the <b>TNCCS 2.0 </b> client-server interface. TNC server
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 f4ea047..c8e5e8a 100644
--- a/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/carol/etc/strongswan.conf
@@ -10,6 +10,11 @@ charon {
     eap-tnc {
       protocol = tnccs-1.1
     }
+  }
+}
+
+libimcv {
+  plugins {
     imc-test {
       command = allow
     }
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 4c738ce..9fc9cec 100644
--- a/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/dave/etc/strongswan.conf
@@ -10,6 +10,11 @@ charon {
     eap-tnc {
       protocol = tnccs-2.0
     }
+  }
+}
+
+libimcv {
+  plugins {
     imc-test {
       command = isolate
     }
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 0b1cf10..0d547cb 100644
--- a/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-dynamic/hosts/moon/etc/strongswan.conf
@@ -11,6 +11,7 @@ charon {
       phase2_method = md5
       phase2_piggyback = yes
       phase2_tnc = yes
+      phase2_tnc_method = tnc
     }
     eap-tnc {
       protocol = tnccs-dynamic

-- 
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